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

React State: useEffect and Custom Hooks

Steve Kinney
October 25, 2019
170

React State: useEffect and Custom Hooks

Steve Kinney

October 25, 2019
Tweet

Transcript

  1. What are we going to cover today?
    — A brief introduction to useEffect.
    — Some of the subleties of useEffect that might bite
    you.
    — Revisiting useReducer
    — A tour of some custom hooks.

    View Slide

  2. Side Effects
    So, most of our applications rely on data from the
    outside world. How do we go about fetching that data?
    Previously, we might have used something like
    componentDidMount to fetch our data.

    View Slide

  3. class Application extends Component {
    componentDidMount() {
    fetch(endpoint)
    .then(response => response.json())
    .then(response => {
    this.setState({
    characters: response.results,
    loading: false
    })
    })
    .catch(console.error);
    }
    render() { … }
    }

    View Slide

  4. Basic fetching inside of a component
    https://codesandbox.io/s/asynchronous-state-with-
    hooks-completed-ky03w

    View Slide

  5. const [characters, setCharacters] = useState([]);
    const [loading, setLoading] = useState(true);
    useEffect(() => {
    fetch(endpoint)
    .then(response => response.json())
    .then(response => {
    setCharacters(response.results);
    setLoading(false);
    })
    .catch(console.error);
    }, [endpoint]);

    View Slide

  6. Be Careful with Dependencies
    Demonstration

    View Slide

  7. ESLint has a setting to help with this: react-hooks/
    exhaustive-deps.

    View Slide

  8. Some Other Tasting Notes
    — Each render has it's own state and props. Example.
    — This is fundamentally different that how class-based
    components work.
    — Example with a functional component.
    — Example with a class-based component.
    — Example of a functional component mimicking
    the behavior of a class-based component.

    View Slide

  9. Refactoring a Counter with useEffect
    — Starting Example
    — Completed Example

    View Slide

  10. Custom Hooks

    View Slide

  11. useLocalStorage
    Demonstration application.

    View Slide

  12. const useLocalStorage = (key, defaultValue = '') => {
    // This is overly simplistic. Do *not* use this in production.
    let [value, setValue] = useState(() => {
    let value = localStorage.getItem(key);
    if (value) value = JSON.parse(value);
    return value || defaultValue;
    });
    const setValueAndStore = val => {
    localStorage.setItem(key, JSON.stringify(val));
    setValue(val);
    };
    return [value, setValueAndStore];
    };

    View Slide

  13. Using Query Params to Store State
    This is useful for storing ephemeral state.
    — Whether or not a list is sorted ascending or
    descending.
    — Current contents for a search filter.
    — The currently selected module in the Design Editor
    or Studio.
    Here is a demonstration.

    View Slide

  14. npm install use-query-params
    import {
    useQueryParam,
    QueryParamProvider,
    NumberParam
    } from "use-query-params";

    View Slide

  15. render(




    ,
    document.getElementById("root")
    );

    View Slide

  16. const Application = () => {
    const [count, setCount] = useQueryParam("count", NumberParam);
    const increment = () => setCount(count + 1);
    const decrement = () => setCount(count - 1);
    return (

    {count}

    Increment
    Decrement


    );
    };

    View Slide

  17. Using Hooks Based on the State
    of the UI

    View Slide

  18. npm install react-hooks-visible
    import React from 'react'
    import { useVisble } from 'react-hooks-visible'
    const VisibleComponent = () => {
    const [targetRef, visible] = useVisible()
    return (
    This is {Math.floor(visible * 100)} % visible
    )
    }

    View Slide

  19. npm install react-hooks-visible
    It also takes a function as an argument.
    // Percent value.
    const [targetRef, percent] = useVisible((amountVisible) => Math.floor(amountVisible* 100))
    // Boolean. This example is 50% visible.
    const [targetRef, isVisible] = useVisible((amountVisible) => amountVisible> 0.5)
    // CSSProperties. opacity
    const [styleExampleRef, visibleStyle] = useVisible((amountVisible) => ({
    opacity: amountVisible
    }))

    View Slide

  20. react-use-scrollspy
    GitHub repository
    const sectionRefs = [
    useRef(null),
    useRef(null),
    useRef(null),
    ];
    const activeSection = useScrollSpy({
    sectionElementRefs: sectionRefs,
    offsetPx: -80,
    });

    View Slide

  21. npm install @rehooks/usePosition
    import { useRef } from 'react';
    import usePosition from '@rehooks/usePosition';
    function MyComponent() {
    let ref = useRef(null);
    let { left, top } = usePosition(ref);
    return (
    Hello Hooks: {JSON.stringify({left, top})}
    );
    }

    View Slide

  22. Miscellaneous Fun Hooks

    View Slide

  23. use-clippy
    Example
    const Application = () => {
    const ref = useRef();
    const [clipboardContent, setClipboardContent] = useClippy();
    useEffect(() => {
    ref.current.focus();
    }, [clipboardContent]);
    return (

    {clipboardContent}

    Edit Clipboard Content:{" "}
    ref={ref}
    type="text"
    value={clipboardContent}
    onChange={e => setClipboardContent(e.target.value)}
    />


    );
    };

    View Slide

  24. useMiddleware
    Danger Zone: I haven't actually used this one.
    const [state, dispatch] = useMiddleware(reducer, initialState, middlewares = []);

    View Slide