Pro Yearly is on sale from $80 to $50! »

the new react

the new react

Ed35943d3199ea37b1b60c39615e8163?s=128

Raphael Amorim

November 06, 2018
Tweet

Transcript

  1. The New React Lifecycles @raphamorims

  2. Hi, I’m Raphael アモリム

  3. None
  4. ^react@16.7.0

  5. • Official Context API • createRef API • forwardRef API

    • Component Lifecycle Changes What’s New?
  6. • Official Context API • createRef API • forwardRef API

    • Component Lifecycle Changes What’s New?
  7. • Official Context API • createRef API • forwardRef API

    • Component Lifecycle Changes What’s New?
  8. • Official Context API • createRef API • forwardRef API

    • Component Lifecycle Changes What’s New?
  9. • Official Context API • createRef API • forwardRef API

    • Component Lifecycle Changes • Strict Mode What’s New?
  10. • Official Context API • createRef API • forwardRef API

    • Component Lifecycle Changes • Strict Mode • React Hooks What’s New?
  11. New context API const ThemeContext = React.createContext('light');

  12. New context API const ThemeContext = React.createContext('light'); class ThemeProvider extends

    React.Component { state = {theme: 'light'}; render() { return ( <ThemeContext.Provider value={this.state.theme}> {this.props.children} </ThemeContext.Provider> ); } }
  13. New context API class ThemedButton extends React.Component { render() {

    return ( <ThemeContext.Consumer> {theme => <Button theme={theme} />} </ThemeContext.Consumer> ); } }
  14. createRef class InputComponent extends Component { constructor(props) { super(props); this.inputRef

    = React.createRef(); } componentDidMount() { this.inputRef.current.focus(); } render() { return <input type="text" ref={this.inputRef} />; } }
  15. Callback refs will continue to be supported in addition to

    the new createRef API. You don’t need to replace callback refs in your components.
  16. const FancyButton = React.forwardRef((props, ref) => ( <button ref={ref} className="FancyButton">

    {props.children} </button> )); // You can now get a ref directly to the DOM button: const ref = React.createRef(); <FancyButton ref={ref}>Click me!</FancyButton>; fowardRef
  17. import React from 'react'; function Application() { return ( <div>

    <Header /> <React.StrictMode> <div> <ComponentOne /> <ComponentTwo /> </div> </React.StrictMode> <Footer /> </div> ); } StrictMode * StrictMode is a tool for highlighting potential problems in an application. Like Fragment, StrictMode does not render any visible UI. 
 It activates additional checks and warnings for its descendants.
  18. • Identifying components with unsafe lifecycles • Warning about legacy

    string ref API usage • Warning about deprecated findDOMNode usage • Detecting unexpected side effects • Detecting legacy context API StrictMode
  19. StrictMode

  20. StrictMode You probably are like this:

  21. StrictMode No one likes a lint error, but it is

    useful.
  22. New and the Old React Lifecycles

  23. Legacy lifecycles will continue to work until version 17. New

    and the Old React Lifecycles
  24. • componentWillMount • componentWillReceiveProps • componentWillUpdate Deprecated now and will

    be removed in React 17
  25. • UNSAFE_componentWillMount • UNSAFE_componentWillReceiveProps • UNSAFE_componentWillUpdate Works on React 17

    * Works with some bugs
  26. • getDerivedStateFromProps • getSnapshotBeforeUpdate New lifecycles

  27. getDerivedStateFromProps

  28. getDerivedStateFromProps // Before class ExampleComponent extends React.Component { state =

    { isScrollingDown: false, }; componentWillReceiveProps(nextProps) { if (this.props.currentRow !== nextProps.currentRow) { this.setState({ isScrollingDown: nextProps.currentRow > this.props.currentRow, }); } } }
  29. // After class ExampleComponent extends React.Component { // Initialize state

    in constructor, // Or with a property initializer. state = { isScrollingDown: false, lastRow: null, }; static getDerivedStateFromProps(props, state) { if (props.currentRow !== state.lastRow) { return { isScrollingDown: props.currentRow > state.lastRow, lastRow: props.currentRow, }; } // Return null to indicate no change to state. return null; } }
  30. getSnapshotBeforeUpdate

  31. // Before class ScrollingList extends Component { listRef = null;

    previousScrollOffset = null; componentWillUpdate(nextProps, nextState) { // Are we adding new items to the list? // Capture the scroll position so we can adjust scroll later. if (this.props.list.length < nextProps.list.length) { this.previousScrollOffset = this.listRef.scrollHeight - this.listRef.scrollTop; } } componentDidUpdate(prevProps, prevState) { // If previousScrollOffset is set, we've just added new items. // Adjust scroll so these new items don't push the old ones out of view. if (this.previousScrollOffset !== null) { this.listRef.scrollTop = this.listRef.scrollHeight - this.previousScrollOffset; this.previousScrollOffset = null; } } ...
  32. class ScrollingList extends Component { listRef = null; getSnapshotBeforeUpdate(prevProps, prevState)

    { // Are we adding new items to the list? // Capture the scroll position so we can adjust scroll later. if (prevProps.list.length < this.props.list.length) { return ( this.listRef.scrollHeight - this.listRef.scrollTop ); } return null; } componentDidUpdate(prevProps, prevState, snapshot) { // If we have a snapshot value, we've just added new items. // Adjust scroll so these new items don't push the old ones out of view. // (snapshot here is the value returned from getSnapshotBeforeUpdate) if (snapshot !== null) { this.listRef.scrollTop = this.listRef.scrollHeight - snapshot; } } ...
  33. None
  34. reactjs.org/blog/2018/03/27/update-on-async-rendering.html Further Reading

  35. migrating it.

  36. github.com/facebook/jscodeshift

  37. github.com/reactjs/react-codemod

  38. $ jscodeshift -t ./unsafe-mod.js ./src --parser=flow -t <path to transform

    file>
  39. $ jscodeshift -t ./unsafe-mod.js ./src --parser=flow files or directory to

    transform -t <path to transform file>
  40. $ jscodeshift -t ./unsafe-mod.js ./src --parser=flow files or directory to

    transform -t <path to transform file>
  41. - "enzyme": "^3.3.0", - "enzyme-adapter-react-16": “^1.1.1” - "react-test-renderer": "^16.2.0", +

    "enzyme": "^3.6.0", + "enzyme-adapter-react-16": “^1.5.0", + "react-test-renderer": “^16.5.1",
  42. - wrapper.instance().componentWillMount(); + wrapper.instance().UNSAFE_componentWillMount();

  43. Hooks

  44. None
  45. https://reactjs.org/docs/ hooks-intro.html

  46. Hooks import { useState } from 'react'; function Example() {

    // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
  47. Looks like Recompose. Feels like Recompose.

  48. import { useState, useEffect } from 'react'; function Example() {

    const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
  49. class Example extends React.Component { constructor(props) { super(props); this.state =

    { count: 0 }; } componentDidMount() { document.title = `You clicked ${this.state.count} times`; } componentDidUpdate() { document.title = `You clicked ${this.state.count} times`; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } }
  50. Cleanup

  51. class FriendStatus extends React.Component { constructor(props) { super(props); this.state =

    { isOnline: null }; this.handleStatusChange = this.handleStatusChange.bind(this); } componentDidMount() { ChatAPI.subscribeToFriendStatus( this.props.friend.id, this.handleStatusChange ); } componentWillUnmount() { ChatAPI.unsubscribeFromFriendStatus( this.props.friend.id, this.handleStatusChange ); } handleStatusChange(status) { this.setState({ isOnline: status.isOnline }); } render() {
  52. import { useState, useEffect } from 'react'; function FriendStatus(props) {

    const [isOnline, setIsOnline] = useState(null); function handleStatusChange(status) { setIsOnline(status.isOnline); } useEffect(() => { ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); // Specify how to clean up after this effect: return function cleanup() { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; }
  53. Cleanup

  54. // Create a Context const NumberContext = React.createContext(); // It

    returns an object with 2 values: // { Provider, Consumer } const context = useContext(Context);
  55. Basic Hooks useState useEffect useContext Additional Hooks useReducer useCallback useMemo

    useRef useImperativeMethods useMutationEffect useLayoutEffect
  56. https:// reactjs.org/blog/2018/03/29/ react-v-16-3.html

  57. https://reactjs.org/docs/ hooks-reference.html