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

Rethinking in React 16

Rethinking in React 16

New Features in React 16. x

More Decks by Manjula Subhashchandra Dube

Other Decks in Programming

Transcript

  1. • Split separable work into chunks. • Pause work and

    come back to it later. • Reuse previously completed work. • Abort work.
  2. React 16 runs in compatibility mode that for the most

    part is equivalent to how React 15 scheduled rendering.
  3. import React, { Component } from "react" class MyComponent extends

    Component { render() { return ( <button radius="4" className="cart”> <span>Add to Cart</span> </button> <span className="buyWrapper">Buy</span> ) } } export default MyComponent
  4. import React, { Fragment } from "react"; render() { return

    ( <Fragment> <button radius="4" className="cart"> <span>Add to Cart</span> </button> <span className="buyWrapper"> Buy </span> </Fragment> ) }
  5. React.createElement(Fragment, null, React.createElement("button", { radius: "4", className: "cart" }, React.createElement("span",

    null, "Add to Cart")), React.createElement("span", { className: "buyWrapper" }, "Buy"));
  6. Problem #2 JavaScript errors inside components used to corrupt React’s

    internal state and cause it to emit cryptic errors on next renders.
  7. class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state =

    { hasError: false }; } componentDidCatch(error, info) { this.setState({ hasError: true }); logErrorToMyService(error, info); } render() { if (this.state.hasError) { return <h1>Something wentwrong.</h1> } return this.props.children; } } <ErrorBoundary> <MyComponent /> </ErrorBoundary>
  8. <div boxname="test" /> // will be displayed in React 15

    as: <div /> <div boxname="test" /> // will be displayed in React 16 as: <div boxname="test" />
  9. import React from 'react'; import ReactDOM from 'react-dom'; const myContext

    = React.createContext('hello') const myProvider = ({children})=> <myContext.Provider value="world"> {children} </myContext.Provider> Provider
  10. import React from 'react'; import ReactDOM from 'react-dom'; const myContext

    = React.createContext('hello') const myProvider = ({children})=> <myContext.Provider value="hello world"> {children} </myContext.Provider>)
  11. import React from 'react'; import ReactDOM from 'react-dom'; const myContext

    = React.createContext('hello') const myProvider = ({children})=> <myContext.Provider value="world"> {children} </myContext.Provider>
  12. import React from 'react'; import ReactDOM from 'react-dom'; const myContext

    = React.createContext('hello') const myProvider = ({children})=> <myContext.Provider value="world"> {children} </myContext.Provider>) const App = () => ( <myProvider
  13. Consumer const App = () => ( <myProvider> </myContext.Consumer> {context

    => <h1> Hello, {context}! </h1>} </myContext.Consumer> </myProvider> )
  14. Consumer const App = () => ( <myProvider> <myContext.Consumer> {context

    => <h1> Hello, {context}! </h1>} </myContext.Consumer> </myProvider> )
  15. Consumer const App = () => ( <myProvider> <myContext.Consumer> {context

    => <h1> Hello, {context}! </h1>} </myContext.Consumer> </myProvider> )
  16. The old context API will keep working for all React

    16.x releases, so you will have time to migrate. Dont Worry
  17. Portals provide a first-class way to render children into a

    DOM node that exists outside the DOM hierarchy of the parent component.
  18. Types of API Legacy String Refs Newer Callback Refs Amazing

    Object Refs Super amazing forwardRef API
  19. Legacy String Ref class Hello extends Component { componentDidMount (){

    this.refs.myRef.focus(); } render() { return ( <div className="App"> <input type="text" ref="myRef"/> </div> ); } }
  20. class Hello extends Component { componentDidMount(){ this.refs.myRef.focus(); } render() {

    return ( <div className="App"> <input type="text" ref="myRef"/> </div> ); } }
  21. class Hello extends Component { componentDidMount(){ this.refs.myRef.focus(); } render() {

    return ( <div className="App"> <input type="text" ref="myRef"/> </div> ); } }
  22. class Hello extends Component { componentDidMount(){ this.myRef.focus(); } render() {

    return ( <div className="App"> <input type="text" ref="{element => this.myRef = element}"/> </div> ); } }
  23. class Hello extends Component { componentDidMount(){ this.myRef.focus(); } render() {

    return ( <div className="App"> <input type="text" ref="{element => this.myRef = element}"/> </div> ); } }
  24. class Hello extends Component { myRef = React.createRef() componentDidMount(){ this.myRef.current.focus();

    } render() { return ( <div className="App"> <input type="text" ref={this.myRef}/> </div> ); } }
  25. class Hello extends Component { myRef = React.createRef() componentDidMount(){ this.myRef.current.focus();

    } render() { return ( <div className="App"> <input type="text" ref={this.myRef}/> </div> ); } }
  26. class Hello extends Component { myRef = React.createRef() componentDidMount(){ this.myRef.current.focus();

    } render() { return ( <div className="App"> <input type="text" ref={this.myRef}/> </div> ); } }
  27. const MyInput = React.forwardRef((props, ref) => <input ref={ref} {...props} />);

    class App extends React.Component { textInput = React.createRef(); componentDidMount() { this.textInput.current.focus() } render() { return ( <div style={styles}> <MyInput ref={this.textInput} /> </div> ); }}
  28. TAKE AWAYS String Refs will get deprecated Object Refs should

    fit most of our cases Callback Refs can be used for advanced usecase Use forwardsRefs to access nested element
  29. Stores its own state internally, and you query the DOM

    using A ref to find its current value when you need it. This is a bit more like traditional HTML
  30. export default class RepoList extends React.Component { _fetch = async

    () => { const res = await fetch("api/url"); const json = await res.json(); this.setState({repos: json, isLoading: false }); }; componentDidMount() {this.setState({ isLoading: true }, this._fetch); }}
  31. render() { const {repos, isLoading } = this.state; return (

    <div> <h3>My Repo List</h3> {isLoading && repos.length > 0 && ( {repos.map(repo => ( <li key={repo.id}> {repo.title} </li> )} )} </div> ); }
  32. class List extends React.Component { _fetch = async () =>

    { const res = await fetch(this.props.url); const json = await res.json(); this.setState({ list: json, isLoading: false, }); } componentDidMount() {this.setState({ isLoading: true }, this._fetch);} render(){ this.props.render(this.state);} }
  33. const App = () => ( <div> <List url="https://api.github.com/users/manjula91/repos" render={({

    repoList, isLoading }) => ( <div> {isLoading && <h2>Loading...</h2>} {repoList.length > 0 && repoList.map(repo => ( <li key={repo.id}> {repo.full_name} </li> ))} </div> )} /> </div> );
  34. componentWillMount  —  please use componentDidMount instead componentWillUpdate  —  please use

    componentDidUpdate instead componentWillReceiveProps  — a new function, static getDerivedStateFromProps is introduced
  35. componentWillMount  —  please use componentDidMount instead componentWillUpdate  —  please use

    componentDidUpdate instead componentWillReceiveProps  — a new function, static getDerivedStateFromProps is introduced
  36. componentWillMount  —  please use componentDidMount instead componentWillUpdate  —  please use

    componentDidUpdate instead componentWillReceiveProps  — a new function, static getDerivedStateFromProps is introduced
  37. class MyClass extends Component { static getDerivedStateFromProps(nextProps, prevState){ if(nextProps.value !==

    prevState.value){ return ({value:nextProps.value}) } } } getDerivedStateFromProps
  38. class MySample extends Component { listRef = React.createRef() getSnapshotBeforeUpdate (prevProps,prevState){

    return prevProps.list.length < this.props.length ? this.listRef.scrollHeight : null; } componentDidUpdate (prevProps,prevState, snapshot){ if(snapshot != null){ const listRef = this.listRef listRef.scrollTop += listRef.scrollHeight - snapshot } } render (){return <div ref={this.listRef}>{/* ... */}</div>} }
  39. class MySample extends Component { listRef = React.createRef() getSnapshotBeforeUpdate(prevProps,prevState){ return

    prevProps.list.length < this.props.length ? this.listRef.scrollHeight : null; } componentDidUpdate(prevProps,prevState, snapshot){ if(snapshot != null){ const listRef = this.listRef listRef.scrollTop += listRef.scrollHeight - snapshot } } render (){return <div ref={this.listRef}>{/* ... */}</div>} }
  40. class MySample extends Component { listRef = React.createRef() getSnapshotBeforeUpdate(prevProps,prevState){ return

    prevProps.list.length < this.props.length ? this.listRef.scrollHeight : null; } componentDidUpdate(prevProps,prevState, snapshot){ if(snapshot != null){ const listRef = this.listRef listRef.scrollTop += listRef.scrollHeight - snapshot } } render (){return <div ref={this.listRef}>{/* ... */}</div>} }
  41. class MySample extends Component { listRef = React.createRef() getSnapshotBeforeUpdate(prevProps,prevState){ return

    prevProps.list.length < this.props.length ? this.listRef.scrollHeight : null; } componentDidUpdate(prevProps,prevState, snapshot){ if(snapshot != null){ const listRef = this.listRef listRef.scrollTop += listRef.scrollHeight - snapshot } } render (){return <div ref={this.listRef}>{/* ... */}</div>} }
  42. Timeline // will be deprecated in future version of React

    16.x release componentWillReceiveProps(nextProps){} // UNSAFE_ introduced in React 16.3 and will be available till 17.0 UNSAFE_componentWillReceiveProps(nextProps){} // instead use… static getDerivedStateFromProps(nextprops,prevState){}
  43. Timeline // will be deprecated in future version of React

    16.x release componentWillReceiveProps(nextProps){} // UNSAFE_ introduced in React 16.3 and will be available till 17.0 UNSAFE_componentWillReceiveProps(nextProps){} // instead use… static getDerivedStateFromProps(nextprops,prevState){}
  44. Timeline // will be deprecated in future version of React

    16.x release componentWillReceiveProps(nextProps){} // UNSAFE_ introduced in React 16.3 and will be available till 17.0 UNSAFE_componentWillReceiveProps(nextProps){} // instead use… static getDerivedStateFromProps(nextprops,prevState){}
  45. React LifeCycle Compat Polyfill import React from 'react'; import polyfill

    from 'react-lifecycles-compat'; class MyComponent extends React.Component { static getDerivedStateFromProps(nextProps,prevState){} } polyfill(MyComponent); export default MyComponent;
  46. React LifeCycle Compat Polyfill import React from 'react'; import polyfill

    from 'react-lifecycles-compat'; class MyComponent extends React.Component { static getDerivedStateFromProps(nextProps,prevState){} } polyfill(MyComponent); export default MyComponent;
  47. React LifeCycle Compat Polyfill import React from 'react'; import polyfill

    from 'react-lifecycles-compat'; class MyComponent extends React.Component { static getDerivedStateFromProps(nextProps,prevState){} } polyfill(MyComponent); export default MyComponent;
  48. React LifeCycle Compat Polyfill import React from 'react'; import polyfill

    from 'react-lifecycles-compat'; class MyComponent extends React.Component { static getDerivedStateFromProps(nextProps,prevState){} } polyfill(MyComponent); export default MyComponent;
  49. import React, { StrictMode } from 'react'; function ExampleApplication ()

    { return ( <div> <Header /> <StrictMode><div><ComponentOne /><ComponentTwo /></div> <StrictMode> <Footer /> </div> ); }
  50. IDEA OF ASYNC MODE IS import React , {unstable_AsyncMode as

    AsyncMode} const LowPriority = () => <AsyncMode> <SomeComponent/> </AsyncMode>