Slide 1

Slide 1 text

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.

Slide 2

Slide 2 text

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.

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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]);

Slide 6

Slide 6 text

Be Careful with Dependencies Demonstration

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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.

Slide 9

Slide 9 text

Refactoring a Counter with useEffect — Starting Example — Completed Example

Slide 10

Slide 10 text

Custom Hooks

Slide 11

Slide 11 text

useLocalStorage Demonstration application.

Slide 12

Slide 12 text

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]; };

Slide 13

Slide 13 text

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.

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

render( , document.getElementById("root") );

Slide 16

Slide 16 text

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

{count}

Increment Decrement ); };

Slide 17

Slide 17 text

Using Hooks Based on the State of the UI

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

); }

Slide 22

Slide 22 text

Miscellaneous Fun Hooks

Slide 23

Slide 23 text

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

{clipboardContent}

Edit Clipboard Content:{" "} setClipboardContent(e.target.value)} />
); };

Slide 24

Slide 24 text

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