Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A portal to the future

A portal to the future

Fiber release brought with it some pretty cool features but the best is yet to come!

First, let’s talk about array children, error boundaries and renderToStream.

Then, I’ll give you a sneak peak into one of the upcoming features that might change the way you build your React applications. Portals open up a lot of opportunities and traps!

Let’s explore 2 of them: reducing client bundle sizes and easier state management.

Siddharth Kshetrapal

September 14, 2017
Tweet

More Decks by Siddharth Kshetrapal

Other Decks in Technology

Transcript

  1. const MyComponent = () => { return ( <div> <tr><td>Item

    1</td></tr> <tr><td>Item 2</td></tr> </div> ) }
  2. const MyComponent = () => { return ( <div> <tr><td>Item

    1</td></tr> <tr><td>Item 2</td></tr> </div> ) }
  3. const MyComponent = () => { return ( [ <tr><td>Item

    1</td></tr>, <tr><td>Item 2</td></tr> ] ) }
  4. import React from 'react' const MyComponent = () => {

    return ( <ErrorBoundary> <BuggyComponent /> </ErrorBoundary> ) }
  5. import React from 'react' const MyComponent = () => {

    return ( <ErrorBoundary> <BuggyComponent /> </ErrorBoundary> ) }
  6. class ErrorBoundary extends React.Component { constructor(props) { super(props) this.state =

    { hasError: false } } componentDidCatch(error, info) { this.setState({ hasError: true }); } render() { if (this.state.hasError) return <h1>Something broke </h1> else return {this.props.children} } }
  7. class ErrorBoundary extends React.Component { constructor(props) { super(props) this.state =

    { hasError: false } } componentDidCatch(error, info) { this.setState({ hasError: true }); } render() { if (this.state.hasError) return <h1>Something broke </h1> else return {this.props.children} } }
  8. class ErrorBoundary extends React.Component { constructor(props) { super(props) this.state =

    { hasError: false } } componentDidCatch(error, info) { this.setState({ hasError: true }); } render() { if (this.state.hasError) return <h1>Something broke </h1> else return {this.props.children} } }
  9. class ErrorBoundary extends React.Component { constructor(props) { super(props) this.state =

    { hasError: false } } componentDidCatch(error, info) { this.setState({ hasError: true }); } render() { if (this.state.hasError) return <h1>Something broke </h1> else return {this.props.children} } }
  10. 500

  11. import { renderToString } from 'react-dom/server' server.get('/', (req, res) =>

    { const html = renderToString(<App />) res.end(html) })
  12. import { renderToString } from 'react-dom/server' server.get('/', (req, res) =>

    { const html = renderToString(<App />) res.end(html) })
  13. import { renderToString } from 'react-dom/server' server.get('/', (req, res) =>

    { const html = renderToString(<App />) res.end(html) })
  14. import { renderToString } from 'react-dom/server' server.get('/', (req, res) =>

    { const html = renderToString(<App />) res.end(html) })
  15. import { renderToNodeStream } from 'react-dom/server' server.get('/', (req, res) =>

    { renderToNodeStream(<App />) .pipe(res) .on('end', () => res.end()) })
  16. import { renderToNodeStream } from 'react-dom/server' server.get('/', (req, res) =>

    { renderToNodeStream(<App />) .pipe(res) .on('end', () => res.end()) })
  17. import { renderToNodeStream } from 'react-dom/server' server.get('/', (req, res) =>

    { renderToNodeStream(<App />) .pipe(res) .on('end', () => res.end()) })
  18. import { renderToNodeStream } from 'react-dom/server' server.get('/', (req, res) =>

    { renderToNodeStream(<App />) .pipe(res) .on('end', () => res.end()) })
  19. s

  20. si

  21. sid

  22. s

  23. s

  24. s s

  25. class Client extends React.Component { constructor() { super() document.getElementById('cart').innerHTML =

    '' } render() { const cartEl = document.getElementById('cart') return <div> </div> } }
  26. class Client extends React.Component { constructor() { super() document.getElementById('cart').innerHTML =

    '' } render() { const cartEl = document.getElementById('cart') return <div> { ReactDOM.unstable_createPortal(<Cart />, cartEl) } </div> } }
  27. class Client extends React.Component { constructor() { super() document.getElementById('cart').innerHTML =

    '' } render() { const cartEl = document.getElementById('cart') return <div> { ReactDOM.unstable_createPortal(<Cart />, cartEl) } </div> } }
  28. class Client extends React.Component { constructor() { super() document.getElementById('cart').innerHTML =

    '' document.getElementById('menu').innerHTML = '' } render() { const cartEl = document.getElementById('cart') return <div> { ReactDOM.unstable_createPortal(<Cart />, cartEl) } </div> } }
  29. class Client extends React.Component { constructor() { super() document.getElementById('cart').innerHTML =

    '' document.getElementById('menu').innerHTML = '' } render() { const cartEl = document.getElementById('cart') return <div> { ReactDOM.unstable_createPortal(<Cart />, cartEl) } </div> } }
  30. class Client extends React.Component { constructor() { super() document.getElementById('cart').innerHTML =

    '' document.getElementById('menu').innerHTML = '' } render() { const cartEl = document.getElementById('cart') const menuEl = document.getElementById('menu') return <div> { ReactDOM.unstable_createPortal(<Cart />, cartEl) } </div> }
  31. class Client extends React.Component { constructor() { super() document.getElementById('cart').innerHTML =

    '' document.getElementById('menu').innerHTML = '' } render() { const cartEl = document.getElementById('cart') const menuEl = document.getElementById('menu') return <div> { ReactDOM.unstable_createPortal(<Cart />, catdEl) } { ReactDOM.unstable_createPortal(<Menu />, menuEl) } </div>
  32. tomato state: { items: [ { id: 1, count: 0

    }, { id: 2, count: 0 }, ... ]} Menu.js
  33. tomato Menu.js state: { items: [ { id: 1, count:

    0 }, { id: 2, count: 0 }, ... ]}
  34. tomato Menu.js state: { items: [ { id: 1, count:

    0 }, { id: 2, count: 1 }, ... ]} onClick = (item) => { this.setState(...) }
  35. tomato Menu.js state: { items: [ { id: 1, count:

    1 }, { id: 2, count: 1 }, ... ]} onClick = (item) => { this.setState(...) }
  36. tomato Menu.js state: { items: [ { id: 1, count:

    2 }, { id: 2, count: 1 }, ... ]} onClick = (item) => { this.setState(...) }
  37. tomato Menu.js Sidebar.js state: { items: [ { id: 1,

    count: 0 }, { id: 2, count: 0 }, ... ]} onClick = (item) => { this.setState(...) }
  38. tomato Menu.js Sidebar.js state: { items: [ { id: 1,

    count: 0 }, { id: 2, count: 1 }, ... ]} onClick = (item) => { this.setState(...) }
  39. tomato Menu.js Sidebar.js state: { items: [ { id: 1,

    count: 0 }, { id: 2, count: 1 }, ... ]} onClick = (item) => { this.setState(...) }
  40. tomato Menu.js Sidebar.js state: { items: [ { id: 1,

    count: 0 }, { id: 2, count: 0 }, ... ]} onClick = (item) => { this.setState(...) }
  41. tomato state: { items: [ { id: 1, count: 0

    }, { id: 2, count: 0 }, ...]} o Sidebar.js App.js Menu.js
  42. tomato state: { items: [ { id: 1, count: 0

    }, { id: 2, count: 0 }, ...]} o Sidebar.js App.js Menu.js props
  43. tomato state: { items: [ { id: 1, count: 0

    }, { id: 2, count: 0 }, ...]} o Sidebar.js App.js Menu.js
  44. tomato state: { items: [ { id: 1, count: 0

    }, { id: 2, count: 0 }, ...]} o Sidebar.js Menu.js onClick = (item) => this.setState(...) App.js
  45. tomato state: { items: [ { id: 1, count: 0

    }, { id: 2, count: 0 }, ...]} o Sidebar.js Menu.js onClick = (item) => this.setState(...) App.js function
  46. tomato state: { items: [ { id: 1, count: 0

    }, { id: 2, count: 0 }, ...]} o Sidebar.js Menu.js onClick = (item) => this.setState(...) App.js
  47. tomato state: { items: [ { id: 1, count: 0

    }, { id: 2, count: 0 }, ...]} o Sidebar.js Menu.js onClick = (item) => this.setState(...) App.js function call
  48. tomato state: { items: [ { id: 1, count: 0

    }, { id: 2, count: 1 }, ...]} o Sidebar.js onClick = (item) => this.setState(...) App.js Menu.js
  49. tomato Sidebar.js state: { items: [ { id: 1, count:

    0 }, { id: 2, count: 1 }, ...]} o Sidebar.js onClick = (item) => this.setState(...) App.js Menu.js props
  50. tomato Sidebar.js state: { items: [ { id: 1, count:

    0 }, { id: 2, count: 1 }, ...]} o Sidebar.js onClick = (item) => this.setState(...) App.js Menu.js props
  51. tomato { items: [ { id: 1, count: 0 },

    { id: 2, count: 0 }, ...] } Store Sidebar.js Menu.js
  52. tomato { items: [ { id: 1, count: 0 },

    { id: 2, count: 0 }, ...] } Store Sidebar.js Menu.js
  53. tomato { items: [ { id: 1, count: 0 },

    { id: 2, count: 0 }, ...] } Store Sidebar.js Menu.js
  54. tomato { items: [ { id: 1, count: 0 },

    { id: 2, count: 0 }, ...] } Store Sidebar.js Menu.js dispatch('ADD_ITEM', {id: 1})
  55. tomato { items: [ { id: 1, count: 0 },

    { id: 2, count: 1 }, ...] } Store Sidebar.js Menu.js
  56. tomato { items: [ { id: 1, count: 0 },

    { id: 2, count: 1 }, ...] } Store Sidebar.js Menu.js
  57. tomato Menu.js Sidebar.js state: { items: [ { id: 1,

    count: 0 }, { id: 2, count: 0 }, ... ]} onClick = (item) => { this.setState(...) }
  58. tomato Menu.js Sidebar.js state: { items: [ { id: 1,

    count: 0 }, { id: 2, count: 1 }, ... ]} onClick = (item) => { this.setState(...) }
  59. tomato Menu.js Sidebar.js state: { items: [ { id: 1,

    count: 0 }, { id: 2, count: 1 }, ... ]} onClick = (item) => { this.setState(...) } render() { // create portal }
  60. tomato Menu.js Sidebar.js state: { items: [ { id: 1,

    count: 0 }, { id: 2, count: 1 }, ... ]} onClick = (item) => { this.setState(...) } render() { // create portal }
  61. class Menu extends React.Component { constructor() { document.getElementById('cart').innerHTML = ''

    } onClick() {...} render() { const cartEl = document.getElementById('cart') return <div> ... { ReactDOM.unstable_createPortal( <Cart items={this.state.items} />, cartEl) } </div> }
  62. class Menu extends React.Component { constructor() { document.getElementById('cart').innerHTML = ''

    } onClick() {...} render() { const cartEl = document.getElementById('cart') return <div> ... { ReactDOM.unstable_createPortal( <Cart items={this.state.items} />, cartEl) } </div> }
  63. class Menu extends React.Component { constructor() { document.getElementById('cart').innerHTML = ''

    } onClick() {...} render() { const cartEl = document.getElementById('cart') return <div> ... { ReactDOM.unstable_createPortal( <Cart items={this.state.items} />, cartEl) } </div> }
  64. class Menu extends React.Component { constructor() { document.getElementById('cart').innerHTML = ''

    } onClick() {...} render() { const cartEl = document.getElementById('cart') return <div> ... { ReactDOM.unstable_createPortal( <Cart items={this.state.items} />, cartEl) } </div> }
  65. class Menu extends React.Component { constructor() { document.getElementById('cart').innerHTML = ''

    } onClick() {...} render() { const cartEl = document.getElementById('cart') return <div> ... { ReactDOM.unstable_createPortal( <Cart items={this.state.items} />, cartEl) } </div> }