A presentation at ReactNext 2018 in November 2018 in Tel Aviv-Yafo, Israel by Yonatan Mevorach
 
                 
                Lessons Learned Reading the Source-code of 18 React Libraries
 
                Yonatan Mevorach @cowchimp
 
                 
                9,000
 
                 
                 
                 
                api implementation
 
                💜
 
                 
                export default class OnlineIndicator extends Component { state = { isOnline: true //TODO: 🤔 } render() { return this.state.isOnline ? ( <OnlineIcon /> ) : ( <OfflineIcon /> ); } }
 
                react-network
 
                <Network render={({ online }) => {online ? ( <OnlineIcon /> ) : ( <OfflineIcon /> )} }/>
 
                 
                export default class Network extends Component { static defaultProps = { render: () => null, onChange: () => {} } state = { online: window.navigator.onLine } componentDidMount() { window.addEventListener("offline", this.onChange) window.addEventListener("online", this.onChange) this.props.onChange(this.state) } componentWillUnmount() { window.removeEventListener("offline", this.onChange) window.removeEventListener("online", this.onChange) } onChange = () => { const online = window.navigator.onLine this.props.onChange({ online }) this.setState({ online }) } render() { return this.props.render(this.state) } }
 
                export default class Network extends Component { static defaultProps = { render: () => null, onChange: () => {} } state = { online: window.navigator.onLine } componentDidMount() { window.addEventListener("offline", this.onChange) window.addEventListener("online", this.onChange) this.props.onChange(this.state) } componentWillUnmount() { window.removeEventListener("offline", this.onChange) window.removeEventListener("online", this.onChange) } onChange = () => { const online = window.navigator.onLine this.props.onChange({ online }) this.setState({ online }) } render() { return this.props.render(this.state) } }
 
                export default class Network extends Component { static defaultProps = { render: () => null, onChange: () => {} } state = { online: window.navigator.onLine } componentDidMount() { window.addEventListener("offline", this.onChange) window.addEventListener("online", this.onChange) this.props.onChange(this.state) } componentWillUnmount() { window.removeEventListener("offline", this.onChange) window.removeEventListener("online", this.onChange) } onChange = () => { const online = window.navigator.onLine this.props.onChange({ online }) this.setState({ online }) } <Network render={ ({ online }) => { /.../ } }/> render() { return this.props.render(this.state) } }
 
                export default class Network extends Component { static defaultProps = { render: () => null, onChange: () => {} } state = { online: window.navigator.onLine } componentDidMount() { window.addEventListener("offline", this.onChange) window.addEventListener("online", this.onChange) this.props.onChange(this.state) } componentWillUnmount() { window.removeEventListener("offline", this.onChange) window.removeEventListener("online", this.onChange) } onChange = () => { const online = window.navigator.onLine this.props.onChange({ online }) this.setState({ online }) } render() { return this.props.render(this.state) } }
 
                export default class Network extends Component { static defaultProps = { render: () => null, onChange: () => {} } state = { online: window.navigator.onLine } componentDidMount() { window.addEventListener("offline", this.onChange) window.addEventListener("online", this.onChange) this.props.onChange(this.state) } componentWillUnmount() { window.removeEventListener("offline", this.onChange) window.removeEventListener("online", this.onChange) } onChange = () => { const online = window.navigator.onLine this.props.onChange({ online }) this.setState({ online }) } render() { return this.props.render(this.state) } }
 
                export default class Network extends Component { static defaultProps = { render: () => null, onChange: () => {} } state = { online: window.navigator.onLine } componentDidMount() { window.addEventListener("offline", this.onChange) window.addEventListener("online", this.onChange) this.props.onChange(this.state) } componentWillUnmount() { window.removeEventListener("offline", this.onChange) window.removeEventListener("online", this.onChange) } onChange = () => { const online = window.navigator.onLine this.props.onChange({ online }) this.setState({ online }) } render() { return this.props.render(this.state) } }
 
                react-*
 
                export default class CheapMediaQuery extends Component { static defaultProps = { render: () => null } state = { screenWidth: window.screen.width } componentDidMount() { window.addEventListener("resize", this.onChange) } componentWillUnmount() { window.removeEventListener("resize", this.onChange) } onChange = () => { this.setState({ screenWidth: window.screen.width }) } render() { return this.props.render(this.state) } }
 
                export default class CheapClock extends Component { static defaultProps = { render: () => null } state = { datetime: new Date() } componentDidMount() { this.intervalId = setInterval(this.onChange, 1000) } componentWillUnmount() { clearInterval(this.intervalId) } onChange = () => { this.setState({ datetime: new Date() }) } render() { return this.props.render(this.state) } }
 
                LESSON #1: Abstract away the Browser’s APIs by creating your own Declarative React Components
 
                LESSON #2: Use Headless Components & the Render Props pattern to promote reusability & extensibility
 
                LESSON #2 V2: Use Headless Components & the Render Props pattern to promote reusability & extensibility (& children-as-a-function & HOCs)
 
                react-router
 
                 
                export default class CheapRouter extends Component { static defaultProps = { render: () => null } state = { location: window.location.pathname } componentDidMount() { window.addEventListener("popstate", this.onChange) } componentWillUnmount() { window.removeEventListener("popstate", this.onChange) } onChange = () => { this.setState({ location: window.location.pathname }) } render() { return this.props.render(this.state) } }
 
                export default class CheapRouter extends Component { static defaultProps = { render: () => null } state = { location: history.location } componentDidMount() { this.unlisten = history.listen(this.onChange) } componentWillUnmount() { this.unlisten() } onChange = (location) => { this.setState({ location: location }) } render() { return this.props.render(this.state) } }
 
                export default class CheapRouter extends Component { static defaultProps = { render: () => null } state = { location: history.location } componentDidMount() { this.unlisten = history.listen(this.onChange) } componentWillUnmount() { this.unlisten() } onChange = (location) => { this.setState({ location: location }) } render() { return this.props.render(this.state)🤔 } }
 
                <CheapRouter render={({ location }) => <CheapLink location={location} to="/" /> } />
 
                <CheapRouter render={App} /> function App(props) { return ( <Products {...props} /> ) } function Products(props) { return ( <CheapLink location={props.location} to="/" /> ) }
 
                function App() { return ( <CheapRouter> <Products /> </CheapRouter> ) } function Products() { return ( <CheapLink to="/" /> ) }
 
                Context
 
                // CheapRouterContext.js import { createContext } from 'react'; export default createContext();
 
                import CheapRouterContext from './CheapRouterContext'; export default class CheapRouter extends Component { static defaultProps = { render: () => null } state = { location: history.location } componentDidMount() { this.unlisten = history.listen(this.onChange) } componentWillUnmount() { this.unlisten() } onChange = (location) => { this.setState({ location: location }) } render() { return ( ) } }
 
                import CheapRouterContext from './CheapRouterContext'; export default class CheapRouter extends Component { static defaultProps = { render: () => null } state = { location: history.location } componentDidMount() { this.unlisten = history.listen(this.onChange) } componentWillUnmount() { this.unlisten() } onChange = (location) => { this.setState({ location: location }) } render() { return ( <CheapRouterContext.Provider /> ) } }
 
                import CheapRouterContext from './CheapRouterContext'; export default class CheapRouter extends Component { static defaultProps = { render: () => null } state = { location: history.location } componentDidMount() { this.unlisten = history.listen(this.onChange) } componentWillUnmount() { this.unlisten() } onChange = (location) => { this.setState({ location: location }) } render() { return ( <CheapRouterContext.Provider value={this.state} /> ) } }
 
                import CheapRouterContext from './CheapRouterContext'; export default class CheapRouter extends Component { static defaultProps = { render: () => null } state = { location: history.location } componentDidMount() { this.unlisten = history.listen(this.onChange) } componentWillUnmount() { this.unlisten() } onChange = (location) => { this.setState({ location: location }) } render() { return ( <CheapRouterContext.Provider value={this.state} children={this.props.children} /> ) } } <CheapRouter> <Products /> </CheapRouter>
 
                import CheapRouterContext from './CheapRouterContext'; export default class CheapLink extends Component { render() { return ( ) } }
 
                import CheapRouterContext from './CheapRouterContext'; export default class CheapLink extends Component { render() { return ( <CheapRouterContext.Consumer> { ({location}) => console.log(location) } </CheapRouterContext.Consumer> ) } }
 
                LESSON #3: In cases where an entire component sub-tree needs the same data, expose it via Context
 
                react-tracking
 
                export default class FooPage extends React.Component { handleClick() { // ... other stuff } render() { return <a onClick={this.handleClick}>Click Me!</a>; } }
 
                @track({ page: 'FooPage' }) export default class FooPage extends React.Component { handleClick() { // ... other stuff } render() { return <a onClick={this.handleClick}>Click Me!</a>; } }
 
                @track({ page: 'FooPage' }) export default class FooPage extends React.Component { @track({ action: 'click' }) handleClick() { // ... other stuff } render() { return <a onClick={this.handleClick}>Click Me!</a>; } }
 
                const calculator = { add: (n1, n2) => n1+n2 } = const calculator = {} Object.defineProperty( calculator, target 'add', { name configurable: true, enumerable: true, descriptor writable: true, value: (n1, n2) => n1+n2 } )
 
                export default function track(trackingInfo) { return function (...args) { console.log(args); } } [ instance, 'handleClick', { configurable: true, enumerable: false, writable: true, value: Æ’() } ] target name descriptor
 
                export default function track(trackingInfo) { return function (target, name, descriptor) { } }
 
                export default function track(trackingInfo) { return function (target, name, descriptor) { return { configurable: descriptor.configurable, enumerable: descriptor.enumerable, } } }
 
                export default function track(trackingInfo) { return function (target, name, descriptor) { return { configurable: descriptor.configurable, enumerable: descriptor.enumerable, value: function(...args) { } } } }
 
                export default function track(trackingInfo) { return function (target, name, descriptor) { return { configurable: descriptor.configurable, enumerable: descriptor.enumerable, value: function(...args) { trackEvent(trackingInfo); } } } }
 
                export default function track(trackingInfo) { return function (target, name, descriptor) { return { configurable: descriptor.configurable, enumerable: descriptor.enumerable, value: function(...args) { trackEvent(trackingInfo); descriptor.value.apply(this, args); } } } }
 
                LESSON #4: Exposing Decorators lets your users integrate with your library with the minimal amount of boilerplate
 
                 
                const Anchor = styled.acolor: white; ${props => props.primary && color: red; } border: 2px solid white;; <Anchor href="/getting-started" primary> Start </Anchor> <Anchor href="/docs"> Documentation </Anchor>
 
                const Anchor = styled.acolor: white; ${props => props.primary && color: red; } border: 2px solid white;;
<Anchor href="/getting-started" primary> Start </Anchor> <Anchor href="/docs"> Documentation </Anchor>
 
                const Anchor = styled.a(color: white; ${props => props.primary && color: red; } border: 2px solid white;);
' color: white; ${props => props.primary && color: red;} border: 2px solid white; '
VS const Anchor = styled.acolor: white; ${props => props.primary && color: red; } border: 2px solid white;;
🤔
 
                styled.acolor: white; ${props => props.primary && color: red; } border: 2px solid white;
styled.a = function(styles, ...interpolations) { }
 
                styled.acolor: white; ${props => props.primary && color: red; } border: 2px solid white;
styled.a = function(styles, ...interpolations) { console.log(styles); console.log(interpolations); }
 
                styled.acolor: white; ${props => props.primary && color: red; } border: 2px solid white;
styled.a = function(styles, ...interpolations) { console.log(styles); console.log(interpolations); } ['color: white;', 'border: 2px solid white;'] [Æ’(props)]
 
                styled.acolor: white; ${props => props.primary && color: red; } border: 2px solid white;
styled.a = function(styles, ...interpolations) { const rules = interleave(styles, interpolations) console.log(rules); }
 
                styled.acolor: white; ${props => props.primary && color: red; } border: 2px solid white;
styled.a = function(styles, ...interpolations) { const rules = interleave(styles, interpolations) console.log(rules); } ['color: white;', Æ’(props), 'border: 2px solid white;']
 
                <Anchor href="/getting-started" primary> Start </Anchor> [ 'color: white;', Æ’(props), 'border: 2px solid white;' ] {
 
                <Anchor href="/getting-started" primary> Start </Anchor> <Anchor href="/contact" primary> Contact Us </Anchor>
 
                <a style="color:white; color:red; border:2px solid white;" href="/getting-started">Start</a> <a style="color:white; color:red; border:2px solid white;" href="/contact-us">Contact Us</a> 💩
 
                 
                [ 'color: white;', 'color: red;' 'border: 2px solid white;' ] const name = hasher(css);
 
                [ 'color: white;', 'color: red;' 'border: 2px solid white;' ] const name = hasher(css); if (!styleSheet.hasName(name)) { }
 
                [ 'color: white;', 'color: red;' 'border: 2px solid white;' ] const name = hasher(css); if (!styleSheet.hasName(name)) { styleSheet.inject(css, '.' + name); } document.head.append
 
                LESSON #5: Use Tagged Template Literals to make it easy to combine different DSLs with React Code
 
                LESSON #6: You can escape out of the React rendering context, & render anywhere in the DOM
 
                LESSON #6: You can escape out of the React rendering context, & render anywhere in the DOM (but be careful !!!)
 
                cb http://flic.kr/p/yCzHwJ
 
                Thank You @cowchimp blog.cowchimp.com
