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

React v16 and beyond React Fiber

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on. →
Avatar for koba04 koba04
September 24, 2017

React v16 and beyond React Fiber

Avatar for koba04

koba04

September 24, 2017

More Decks by koba04

Other Decks in Programming

Transcript

  1. w SFOEFSؔ਺͔Β௚઀จࣈྻ΍഑ྻΛฦ͢͜ͱ͕Ͱ͖ΔΑ͏ʹ 3FOEFSTUSJOHBOEBSSBZ // จࣈྻ const DisplayName = ({user}) =>

    `${user.name} (@${user.id})`; <DisplayName user={{name: ‘Toru Kobayashi’, id: ‘koba04’}} /> // Toru Kobayashi (@koba04) // ഑ྻ const Row = ({children}) => <tr>{children}</tr>; const Columns = ({items}) => ( items((item, i) => <td key={i}>{item}</td> ); <Row> <Columns items={[‘foo’, ‘bar’, ‘baz’]} /> </Row>
  2. &SSPS#PVOEBSJFT class Child extends React.Component { componentDidMount() { throw new

    Error(‘Something went wrong!!’); } } class App extends React.Component { constructor(props) { super(props); this.state = { error: null }; } componentDidCatch(error, info) { // info.componentStack͸ComponentͷStackTraceจࣈྻ this.setState(() => ({error})); } render() { return this.state.error ? <p>Τϥʔ͕ൃੜ͠·ͨ͠</p> : <Child />; } }
  3. w 1PSUBMΛ࢖Θͳ͍ྫ 1PSUBM class App extends React.Component { componentDidUpdate() {

    const container = document.querySelector(‘.modal-container’); if (this.state.modal) { ReactDOM.render( <Modal type={this.state.modal} onClose={() => { this.setState( () => ({modal: null}), () => ReactDOM.unmountComponentAtNode(container) ); }} />, container ); } } }
  4. w 1PSUBMΛ࢖ͬͨ৔߹ 1PSUBM class App extends React.Component { render() {

    return ( <section> <Contents /> {this.state.modal && ReactDOM.createPortal( <Modal type={this.state.modal} onClose={() => { this.setState(() => ({modal: null})); } />, document.querySelector(‘.modal-container’) )} </section> ); } }
  5. 'MBU#VOEMFT node_modules/react "## cjs $ "## react.development.js $ %## react.production.min.js

    "## index.js node_modules/react-dom "## cjs $ "## react-dom-server.browser.development.js $ "## react-dom-server.browser.production.min.js $ "## react-dom-server.node.development.js $ "## react-dom-server.node.production.min.js $ "## react-dom-test-utils.development.js $ "## react-dom-unstable-native-dependencies.development.js $ "## react-dom-unstable-native-dependencies.production.min.js $ "## react-dom.development.js $ %## react-dom.production.min.js "## index.js
  6. w ׬શʹಠཱͨ͠3FOEFSFSʹʢطଘ࣮૷͕ϕʔεʣ w 3FBDU1BSUJBM3FOEFSFSKTͱ͍͏ϑΝΠϧ - ʹ w 4USFBN3FOEFSJOHͷαϙʔτ w )ZESBUJPO4USBUFHZͷมߋ

    w )ZESBUJPOʜ443ͨ͠)5.-ΛΫϥΠΞϯτͰͷϨϯμϦ ϯά࣌ʹ࠶ར༻͢Δ w 3FBDU%0.IZESBUF ͷ௥Ճ 4FSWFS4JEF3FOEFSJOH
  7. w SFOEFS5P/PEF4USFBN SFOEFS5P4UBUJD/PEF4USFBNͷ௥Ճ 4USFBN3FOEFSJOH import ReactDOMServer from ‘react-dom/server’; const App

    = () => ( <div> <p>Hello Stream!</p> </div> ); ReactDOMServer.renderToNodeStream(<App />).pipe(process.stdin); // <div data-reactroot=""><p>Hello Stream!</p></div> ReactDOMServer.renderToStaticNodeStream(<App />).pipe(process.stdin); // <div><p>Hello Stream!</p></div>
  8. w 3FBDU%0.IZESBUF ͱ͍͏໌ࣔతͳ"1*ͷ௥Ճ w WͰ͸ɺ3FBDU%0.SFOEFS ʹΑΔ)ZESBUF΋Ҿ͖ଓ͖ αϙʔτʢAEBUBSFBDUSPPUAଐੑʹΑͬͯ൑ఆʣ w 3FBDU&MFNFOUͷ୯ҐͰՄೳͳݶΓ࠶ར༻͞ΕΔΑ͏ʹ w

    W·Ͱ͸ɺ%0.ߏ଄͕׬શʹҰக͢Δ͔Ͳ͏͔ΛνΣο ΫαϜʹΑͬͯ൑ఆ w /PNPSFAEBUBSFBDUDIFDLTVNABOEAEBUBSFBDUJEA )ZESBUJPO4USBUFHZ
  9. w ϗϫΠτϦετʹͳ͍ଐੑ΋%0.ʹ൓ө͞ΕΔΑ͏ʹ w WͰ͸ɺXBSOJOHTUSJQ w ADMBTTA΍AGPSA΍APOʙAͳͲ͸আ͘ w ෆਖ਼ͳܕͷଐੑ஋͸TUSJQ͞ΕΔΑ͏ʹ w WͰ͸ɺจࣈྻԽͯ͠ద༻͞Ε͍ͯͨ

    %0."UUSJCVUFT <div someExperimentalAttribute=“foo” /> <div className={false} /> // v16 <div /> & warning // v15 <div className=“false” /> .PSFIUUQTGBDFCPPLHJUIVCJPSFBDUCMPHEPNBUUSJCVUFTJOSFBDUIUNM
  10. w .BQ 4FU SFRVFTU"OJNBUJPO'SBNF͕ඞཁʹ w αϙʔτ͢Δϒϥ΢βʔʹԠͯ͡1PMZpMMΛೖΕΔ 1PMZpMM import ‘core-js/es6/map’; import

    ‘core-js/es6/set’; import raf from ‘raf’; if (!window.requestAnimationFrame) { window.requestAnimationFrame = raf; }
  11. SFRVFTU*EMF$BMMCBDL const work = (deadline) => { if (deadline.timeRemaining() >

    10) { // do some heavy tasks } else { requestIdleCallback(work); } }; requestIdleCallback(work); Fig. 1 Example of an inter-frame idle period (https://www.w3.org/TR/requestidlecallback/)
  12. 'JCFSͷσʔλߏ଄ export type Fiber = {| tag: TypeOfWork, key: null

    | string, type: any, stateNode: any, return: Fiber | null, child: Fiber | null, sibling: Fiber | null, index: number, ref: null | (((handle: mixed) => void) & {_stringRef: ?string}), pendingProps: any, memoizedProps: any, updateQueue: UpdateQueue | null, memoizedState: any, internalContextTag: TypeOfInternalContext, effectTag: TypeOfSideEffect, nextEffect: Fiber | null, firstEffect: Fiber | null, lastEffect: Fiber | null, pendingWorkPriority: PriorityLevel, alternate: Fiber | null, _debugID?: DebugID, _debugSource?: Source | null, _debugOwner?: Fiber | ReactInstance | null, _debugIsCurrentlyTiming?: boolean, |};
  13. -JOLFE-JTUߏ଄ let root = fiber; let node = fiber; while

    (true) { // Do something with node if (node.child) { node = node.child; continue; } if (node === root) { return; } while (!node.sibling) { if (!node.return || node.return === root) { return; } node = node.return; } node = node.sibling; } From: Fiber Principles: Contributing To Fiber #7942 https://github.com/facebook/react/issues/7942
  14. Text = () => '...'; List = () => [

    <div>...</div>, <div>...</div>, ]; class App extends React.Component { render() { return ( <main> <h2>...</h2> <div> <Text /> <List /> </div> </main> ); } } ReactDOM.render(<App />, container) HostRoot <App /> <main /> <h2 /> <div /> <Text /> HostText List <div /> <div /> 1 2 3 4 5 6 8 9 10 7 Ͳ͔͜ΒͰ΋தஅʙ࠶։ Ͱ͖Δ
  15. w 3FBDU'JCFS͸l#FHJOz l$PNQMFUFz l$PNNJUzͷϑΣʔζΛ࣋ͬͯ ͍Δ w #FHJOʙ$PNQMFUF w 'JCFS $PNQPOFOU

    ͷ୯ҐͰॲཧ͞ΕΔ w Πϯελϯεͷ࡞੒ɺSFOEFSؔ਺ͷ࣮ߦ ࠩ෼ܭࢉ w $PNNJU w ߋ৽ॲཧͷ୯ҐͰॲཧ͞ΕΔ w ෭࡞༻Λ·ͱΊͯ൓ө͢Δ %0.ͷߋ৽ͳͲ 1IBTFT
  16. w #FHJOϑΣʔζ w DPNQPOFOU8JMM.PVOU DPNQPOFOU8JMM3FDFJWF1SPQT  TIPVME$PNQPOFOU6QEBUF DPNQPOFOU8JMM6QEBUF w ඇಉظ3FOEFSJOHͰ͸ɺதஅʙ࠶։͞ΕΔ͜ͱͰෳ਺ճݺ

    ͹ΕΔ͜ͱ΋ w $PNNJUϑΣʔζ w DPNQPOFOU%JE.PVOU DPNQPOFOU%JE6QEBUF  DPNQPOFOU8JMM6ONPVOU ϥΠϑαΠΫϧϝιου
  17. ෭࡞༻͸·ͱΊͯҰ౓Ͱ൓ө͞ΕΔ FiberA FiberB FiberD FiberE Commit all SideEffects Idle Time

    Idle Time Idle Time Beginʙ Complete SideEffect SideEffect SideEffect Host (DOM) FiberC
  18. )JHI1SJPSJUZͷߋ৽ॲཧ͸ׂΓࠐΈͰ͖Δ FiberA FiberB FiberA FiberC Commit Low Priority High Priority

    Commit FiberA FiberB FiberC Low Priority ࠶ར༻ ׂΓࠐΈʂ தஅ
  19. w %0.3FOEFSFSͷ৔߹͸ɺIJEEFO1SPQΛ࢖͏ 0⒎4DSFFO1SJPSJUZ App = () => ( <div> <ul

    hidden> <li>xxx</li> : 1000items <li>xxx</li> </ul> <ul> <li>xxx</li> : 1000items <li>xxx</li> </ul> </div> ); ReactDOM.render(<App />, container);
  20. w %0.3FOEFSFSͷ৔߹͸ɺIJEEFO1SPQΛ࢖͏ 0⒎4DSFFO1SJPSJUZ App = () => ( <div> <ul

    hidden> <li>xxx</li> : 1000items <li>xxx</li> </ul> <ul> <li>xxx</li> : 1000items <li>xxx</li> </ul> </div> ); ReactDOM.render(<App />, container); ݱ࣌఺Ͱ͸ɺFeatureϑϥάʹΑͬͯӅ͞Ε͍ͯΔ
  21. ඇಉظ3FOEFSJOHΛࢼ͢ // Low PriorityʹΑΔߋ৽ ReactDOM.unstable_deferredUpdates(() => { this.setState(updater); }); //

    ߋ৽͕Low Priorityͱͯ͠ѻΘΕΔComponent const AsyncComponent = React.unstable_AsyncComponent; <AsyncComponent> <App /> </AsyncComponent> // or class App extends AsyncComponent { onClick() { // Sync Priority ReactDOM.flushSync(() => this.setState(() => newState)); } }
  22. ඇಉظ3FOEFSJOHΛࢼ͢ // Low PriorityʹΑΔߋ৽ ReactDOM.unstable_deferredUpdates(() => { this.setState(updater); }); //

    ߋ৽͕Low Priorityͱͯ͠ѻΘΕΔComponent const AsyncComponent = React.unstable_AsyncComponent; <AsyncComponent> <App /> </AsyncComponent> // or class App extends AsyncComponent { onClick() { // Sync Priority ReactDOM.flushSync(() => this.setState(() => newState)); } } v17Ҏ߱ͰͷAPI͸ݱ࣌఺Ͱ͸ະఆ
  23. w $VTUPN3FOEFSFSΛ࣮૷͢ΔͨΊͷํ๏͕ఏڙ͞ΕΔ w ASFBDUSFDPODJMFSA  w 3FBDUSFDPODJMFSQBDLBHF w IUUQTHJUIVCDPNGBDFCPPLSFBDUQVMM w

    'MPXUZQFʹΑͬͯΠϯλʔϑΣΠε͕ఆٛ͞Ε͍ͯΔ w IUUQTHJUIVCDPNGBDFCPPLSFBDUCMPCNBTUFSTSD SFOEFSFSTTIBSFEpCFS3FBDU'JCFS3FDPODJMFSKT $VTUPN3FOEFSFS
  24. $VTUPN3FOEFSFS $POTPMF ReactConsole.render( <div> <red>Hello</red> <yellow>World</yellow> <cyan>React</cyan> <rainbow>Custom Renderer!</rainbow> </div>,

    () => console.log( colors.inverse('##### Update ######’) ) ); ReactConsole.render( <div> <green>Hello</green> <yellow>World2</yellow> <cyan>React</cyan> </div> ); IUUQTHJTUHJUIVCDPNLPCBDCECEGBFDB
  25. $VTUPN3FOEFSFS 7PJDF ReactVoice.render([ <alex key={1}>Hello</alex>, <victoria key={2}>React Fiber</victoria>, <kyoko key={3}>͜Μʹͪ͸

    HTML5 Conference</kyoko>, ]); ??? IUUQTHJTUHJUIVCDPNLPCBFBGDBFBDEFGE
  26. 'VUVSF React Fiber (written by C or C++ or…) Native

    module for ReactNative Web Assembly for ReactDOM