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

React v16 and beyond React Fiber

koba04
September 24, 2017

React v16 and beyond React Fiber

koba04

September 24, 2017
Tweet

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