React Flashcards
List all hooks available
Basic Hooks:
- useState
- useEffect
- useContext
Additional Hooks:
- useReducer
- useCallback
- useMemo
- useRef
- useImperativeHandle
- useLayoutEffect
- useDebugValue
How does the useState hook work ?
const [state, setState] = useState(initialState);
Returns a stateful value, and a function to update it.
During the initial render, the returned state ( state ) is the same as the value passed as the first argument ( initialState ).
the setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.
function Counter({initialCount}) {
const [count, setCount] = useState(initialCount);
return (
<>
Count: {count}
setCount(initialCount)}>Reset
setCount(prevCount => prevCount + 1)}>+
setCount(prevCount => prevCount - 1)}>-
>
);
}
How does the useEffect hook work ?
useEffect(didUpdate);
It accepts a function that contains imperative, possibly effectful code.
Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase). Doing so will lead to confusing bugs and inconsistencies in the UI.
The function passed to useEffect will run after the render is committed to the screen.
By default, effects run after every completed render, but you can choose to fire it only when certain values have changed.
Cleaning up an effect:
Often, effects create resources that need to be cleaned up before the component leaves the screen, such as a subscription or timer ID. To do this, the function passed to useEffect may return a clean-up function.
useEffect(() => { const subscription = props.source.subscribe(); return () => { // Clean up the subscription subscription.unsubscribe(); }; });
The clean-up function runs before the component is removed from the UI to prevent memory leaks.
The default behavior for effects is to fire the effect after every completed render. That way an effect is always recreated if one of its dependencies changes.
However, this may be overkill in some cases, like the subscription example. We don’t need to create a new subscription on every update, only if the source props has changed.
To implement this, pass a second argument to useEffect that is the array of values that the effect depends on.
useEffect( () => { const subscription = props.source.subscribe(); return () => { subscription.unsubscribe(); }; }, [props.source], );
Now the subscription will only be recreated when props.source changes.
If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ( [ ] ) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.
How does the useContext hook work ?
const value = useContext(MyContext);
It accepts a context object (the value returned from React.createContext) and returns the current context value for that context.
A component calling useContext will always re-render when the context value changes.
useContext(MyContext) only lets you read the context and subscribe to its changes.
How does the useReducer hook work ?
const [state, dispatch] = useReducer(reducer, initialArg, init);
An alternative to useState. It accepts a reducer of type (state, action) => newState, and returns the current state paired with a dispatch method.
useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.
useReducer also lets you optimize performance for components that trigger deep updates because you can pass dispatch down instead of callbacks.
function init(initialCount) { return {count: initialCount}; }
function reducer(state, action) { switch (action.type) { case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; case 'reset': return init(action.payload); default: throw new Error(); } }
function Counter({initialCount}) { const [state, dispatch] = useReducer(reducer, initialCount, init); return ( <> Count: {state.count} dispatch({type: 'reset', payload: initialCount})}>
Reset
dispatch({type: 'increment'})}>+ dispatch({type: 'decrement'})}>- > ); }
How does the useMemo hook work ?
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
It invokes the provided function and caches its result.
It caches a computed value. This is useful when the computation requires significant resources and we don’t want to repeat it on every re-render.
How does the useCallback hook work ?
It caches the provided function instance