Dive into React Perf CT Wu, 2016 @ JSDC Twitter: wu_ct Github: wuct Email: wu.chingting@gmail.com
Better performance leads to better user experience
Use the production version of React
Use a bundler <script src="path/to/react.min.js"></script> <script src="path/to/react-dom.min.js"></script> process.env.NODE_ENV = "production" Use pre-built files
How does React work?
createElement(View, {}, [ createElement(View), createElement(View) ]) <View> <View /> <View /> </View> { type: View, props: { children: [ { type: View }, { type: View }, ] } }
ReactDOM.render( )
setState()
• Reduce call to React.createElement() • Avoid reconciliation • Avoid re-mounting
render() { return ( <table> <thead> <tr> <th>Header 1</th> <th>Header 2</th> </tr> </thead> <tfoot> <tr> <td>Footer 1</td> <td>Footer 2</td> </tr> </tfoot> <tbody> { // ... } </tbody> </table> ) } const headerAndFooter = <thead> <tr> <th>Header 1</th> <th>Header 2</th> </tr> </thead> <tfoot> <tr> <td>Footer 1</td> <td>Footer 2</td> </tr> </tfoot> render() { return ( <table> {headerAndFooter} <tbody> { // ... } </tbody> </table> ) }
setState() bailout
shoudComponentUpdate(nextProps, nextState) { if (/* You want to update */) { return true } return false }
Pure Render Optimization shoudComponentUpdate(nextProps, nextState) { return ( !shallowEqual(nextProps, this.props) || !shallowEqual(nextState, this.state) ) } class extends React.PureComponent { // ... } or
Anti Pure Render render() { return ( <PureComponent inlineFunc={() => {}} funcBind={func.bind(this)} arrayLiteral={[]} newArray={map(…)} objectLiteral={{}} newObject={assign({}, …)} > <NestedChild /> </PureComponent> ) }
Static View Optimization import StaticContainer from 'react-static-container' shoudComponentUpdate() { return false } or
React Internal Bailout • Bailout when prevElement === nextElement • Don’t bailout when prevContext !== nextContext • React always create a new context • Don’t use setState() and getChildContext() in one component
class extends React.Component { getChildContext() { return this.state } componentDidMount() { setInterval(() => this.setState({ time: this.state.time + 1 }) , 1000) } // ... }
• Updating is faster than re-mounting • Don’t change the key or the type if you want to update
render() { return isDarkTheme ? <DarkApp /> : <LightApp /> } render() { <App dark={isDarkTheme} /> }
render () { return ( <List> { data.map(item => <Item key={item.uniqueId} /> ) } </List> ) } render () { return ( <List> { data.map(item => <Item key={Math.random()} /> ) } </List> ) }
React Perf Tool • Currently, only supports the development version of React • Perf.start() • Perf.stop() • Perf.printWasted() • Perf.printOperations()
class Child extends React.Component { render() { return <div /> } } class App extends React.Component { state = { title: 'Foo' } render() { return ( <div> {this.state.title} <Child /> </div> ) } }
Perf.start() app.setState({ title: ‘bar’ }) Perf.stop() Perf.printWasted()
class Child extends React.PureComponent { render() { return <div /> } }
Perf.start() app.setState({ title: ‘bar’ }) Perf.stop() Perf.printWasted()
class App extends React.Component { state = { theme: 'light' } render() { return ( <div> { this.state.theme === 'light' ? <Light /> : <Dark /> } </div> ) } }
Perf.start() app.setState({ theme: 'dark' }) Perf.stop() Perf.printOperations()
class App extends React.Component { state = { theme: 'light' } render() { return ( <div> <Content theme={this.state.theme} /> </div> ) } }
Perf.start() app.setState({ theme: 'dark' }) Perf.stop() Perf.printOperations()
React Fiber • Is still experimental • Prioritization • Return multiple elements from render • Try it now: npm i react-dom@15.4.0-rc.4 import ReactDOMFiber from 'react-dom/fiber'
Thanks! • Github: wuct • Twitter: wu_ct • wu.chingting@gmail.com

Dive into React Performance