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.current

Ref 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: