Hooks
State management
They are used to manage state in react
useState
React exists to better manage state, useState is best for client components that need their own simple state. It returns an array composed by the state variable and the setter. It is great to capture user input, for example, show or hide components, etc.
useReducer
It is useful for more complex state management, since you can pass a function that transform the state from the old state an an action. It is useful for more complex components, like a form with multiple inputs
useSyncExternalStore
You are likely not going to use it, it is useful to integrate non-react state store with React State Store
Effect hooks
Used to perform side effects outside reacts, i.e. set the title by using the DOM API
useEffect
You pass dependencies, and a function. For these two types of side effect:
- event based
- render-based
useEffect shouldn’t not be used .
- You can simply do the side effect in an event-handler for the first case
<div onClick={eventHandler}> - React Query or a framework tool for the second one
You need to use useEffect to sync your React state with your browser API
useLayoutEffect
More limited, runs before paint, but it is synchronous. Useful to get value from a browser API, and then set in the
useInsertionEffect
Runs even before useLayoutEffect and useEffect, only useful for library developers who deal with CSS-in-JS libraries and it is used to insert style
Refs
Refs are an “escape hatch”
useRef
Takes a single value like so:
const ref = useRef(0)
ref.currentRef are mutable, they can modified using the equal operations while state are immutable. Ref updates do not trigger re-rendering
Refs can be used to obtain a reference to a node
const inputEl = useRef(0)
<input ref={inputEl}/>
const handleFocus = () => inputEl.current.focus()useImperativeHandle
A ref hook only when you need to forward a ref to the parent component, for example.
const CustomInput = forwardRef((props, ref)) => {
const inputRef = useRef()
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus()
}
}))
return <input ref={inputRef}/>
})
function ParentComponent() {
const inputRef = useRef()
const handleFocus = () => {
inputRef.current.focus()
}
return <>
<CustomInput ref={inputRef}/>
<button onClick={handleFocus}>Focus input</button>
</>
}Apps performance
useMemo
Will recompute a cache value only when one of its dependencie change. Looks similar to useEffect.
function Component({numbers}){
const sum = useMemo( () => {
return numbers.reduce((total,n) => total + n, 0)
}, [numbers])
return <h1>Sum: {sum}</h1>
}
useCallback
Similar to useMemo, prevent callBack function to be recreated on each re-render when they are for example passed to a child component as a prop
function Button({onClick}){
return <button onClick={onClick}>Click me</button>
}
function Counter(){
const [count, setCount] = useState(0)
const increment = useCallback(() => {
setCount((c) => c + 1)
},[])
return
<>
<div>{count}</div>
<Button onClick={increment}/>
</>
}
Context
If a component is wrapped in a
const ThemeContext = createContext()
<ThemeContext.Provider value="dark">
<MyComponent/>
</ThemeContext>
function MyComponent(){
const theme = useContext(ThemeContext)
}Transitions
useTransition
It is for a non-urgent state transition, i.e. for filtering a list that would trigger too many re-rendering. We can
useDeferredValue
It lets you defer update to keep your app responsive. Let us schedule
React: