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

the new react

the new react

Raphael Amorim

November 06, 2018
Tweet

More Decks by Raphael Amorim

Other Decks in Programming

Transcript

  1. The
    New
    React
    Lifecycles
    @raphamorims

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  9. New context API
    const ThemeContext = React.createContext('light');

    View full-size slide

  10. New context API
    const ThemeContext = React.createContext('light');
    class ThemeProvider extends React.Component {
    state = {theme: 'light'};
    render() {
    return (

    {this.props.children}

    );
    }
    }

    View full-size slide

  11. New context API
    class ThemedButton extends React.Component {
    render() {
    return (

    {theme => }

    );
    }
    }

    View full-size slide

  12. createRef
    class InputComponent extends Component {
    constructor(props) {
    super(props);
    this.inputRef = React.createRef();
    }
    componentDidMount() {
    this.inputRef.current.focus();
    }
    render() {
    return ;
    }
    }

    View full-size slide

  13. 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.

    View full-size slide

  14. const FancyButton = React.forwardRef((props, ref) => (

    {props.children}

    ));
    // You can now get a ref directly to the DOM button:
    const ref = React.createRef();
    Click me!;
    fowardRef

    View full-size slide

  15. import React from 'react';
    function Application() {
    return (










    );
    }
    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.

    View full-size slide

  16. • 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

    View full-size slide

  17. StrictMode
    You probably are like this:

    View full-size slide

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

    View full-size slide

  19. New and the Old React Lifecycles

    View full-size slide

  20. Legacy lifecycles will continue to work until version 17.
    New and the Old React Lifecycles

    View full-size slide

  21. • componentWillMount
    • componentWillReceiveProps
    • componentWillUpdate
    Deprecated now and will be removed in React 17

    View full-size slide

  22. • UNSAFE_componentWillMount
    • UNSAFE_componentWillReceiveProps
    • UNSAFE_componentWillUpdate
    Works on React 17
    * Works with some bugs

    View full-size slide

  23. • getDerivedStateFromProps
    • getSnapshotBeforeUpdate
    New lifecycles

    View full-size slide

  24. getDerivedStateFromProps

    View full-size slide

  25. 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,
    });
    }
    }
    }

    View full-size slide

  26. // 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;
    }
    }

    View full-size slide

  27. getSnapshotBeforeUpdate

    View full-size slide

  28. // 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;
    }
    }
    ...

    View full-size slide

  29. 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;
    }
    }
    ...

    View full-size slide

  30. reactjs.org/blog/2018/03/27/update-on-async-rendering.html
    Further Reading

    View full-size slide

  31. migrating it.

    View full-size slide

  32. github.com/facebook/jscodeshift

    View full-size slide

  33. github.com/reactjs/react-codemod

    View full-size slide

  34. $ jscodeshift -t ./unsafe-mod.js ./src --parser=flow
    -t

    View full-size slide

  35. $ jscodeshift -t ./unsafe-mod.js ./src --parser=flow
    files or directory to transform
    -t

    View full-size slide

  36. $ jscodeshift -t ./unsafe-mod.js ./src --parser=flow
    files or directory to transform
    -t

    View full-size slide

  37. - "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",

    View full-size slide

  38. - wrapper.instance().componentWillMount();
    + wrapper.instance().UNSAFE_componentWillMount();

    View full-size slide

  39. https://reactjs.org/docs/
    hooks-intro.html

    View full-size slide

  40. Hooks
    import { useState } from 'react';
    function Example() {
    // Declare a new state variable, which we'll call "count"
    const [count, setCount] = useState(0);
    return (

    You clicked {count} times
    setCount(count + 1)}>
    Click me


    );
    }

    View full-size slide

  41. Looks like Recompose.
    Feels like Recompose.

    View full-size slide

  42. 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 (

    You clicked {count} times
    setCount(count + 1)}>
    Click me


    );
    }

    View full-size slide

  43. 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 (

    You clicked {this.state.count} times
    this.setState({ count: this.state.count + 1 })}>
    Click me


    );
    }
    }

    View full-size slide

  44. 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() {

    View full-size slide

  45. 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';
    }

    View full-size slide

  46. // Create a Context
    const NumberContext = React.createContext();
    // It returns an object with 2 values:
    // { Provider, Consumer }
    const context = useContext(Context);

    View full-size slide

  47. Basic Hooks
    useState
    useEffect
    useContext
    Additional Hooks
    useReducer
    useCallback
    useMemo
    useRef
    useImperativeMethods
    useMutationEffect
    useLayoutEffect

    View full-size slide

  48. https://
    reactjs.org/blog/2018/03/29/
    react-v-16-3.html

    View full-size slide

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

    View full-size slide