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

React State: useEffect and Custom Hooks

Steve Kinney
October 25, 2019
190

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.
  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.
  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() { … } }
  4. 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]);
  5. 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.
  6. 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]; };
  7. 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.
  8. const Application = () => { const [count, setCount] =

    useQueryParam("count", NumberParam); const increment = () => setCount(count + 1); const decrement = () => setCount(count - 1); return ( <main className="Counter"> <p className="count">{count}</p> <section className="controls"> <button onClick={increment}>Increment</button> <button onClick={decrement}>Decrement</button> </section> </main> ); };
  9. npm install react-hooks-visible import React from 'react' import { useVisble

    } from 'react-hooks-visible' const VisibleComponent = () => { const [targetRef, visible] = useVisible() return ( <div ref={targetRef}>This is {Math.floor(visible * 100)} % visible </div> ) }
  10. 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 }))
  11. react-use-scrollspy GitHub repository const sectionRefs = [ useRef(null), useRef(null), useRef(null),

    ]; const activeSection = useScrollSpy({ sectionElementRefs: sectionRefs, offsetPx: -80, });
  12. 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 ( <p ref={ref}>Hello Hooks: {JSON.stringify({left, top})}</p> ); }
  13. use-clippy Example const Application = () => { const ref

    = useRef(); const [clipboardContent, setClipboardContent] = useClippy(); useEffect(() => { ref.current.focus(); }, [clipboardContent]); return ( <div className="Application"> <p>{clipboardContent}</p> <label> Edit Clipboard Content:{" "} <input ref={ref} type="text" value={clipboardContent} onChange={e => setClipboardContent(e.target.value)} /> </label> </div> ); };
  14. useMiddleware Danger Zone: I haven't actually used this one. const

    [state, dispatch] = useMiddleware(reducer, initialState, middlewares = []);