--- id: hooks-reference title: Hooks API Reference permalink: docs/hooks-reference.html prev: hooks-custom.html next: hooks-faq.html --- *Hooks* are a new addition in React 16.8. They let you use state and other React features without writing a class. This page describes the APIs for the built-in Hooks in React. If you're new to Hooks, you might want to check out [the overview](/docs/hooks-overview.html) first. You may also find useful information in the [frequently asked questions](/docs/hooks-faq.html) section. - [Basic Hooks](#basic-hooks) - [`useState`](#usestate) - [`useEffect`](#useeffect) - [`useContext`](#usecontext) - [Additional Hooks](#additional-hooks) - [`useReducer`](#usereducer) - [`useCallback`](#usecallback) - [`useMemo`](#usememo) - [`useRef`](#useref) - [`useImperativeHandle`](#useimperativehandle) - [`useLayoutEffect`](#uselayouteffect) - [`useDebugValue`](#usedebugvalue) ## Basic Hooks {#basic-hooks} ### `useState` {#usestate} ```js 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. ```js setState(newState); ``` During subsequent re-renders, the first value returned by `useState` will always be the most recent state after applying updates. #### Functional updates {#functional-updates} If the new state is computed using the previous state, you can pass a function to `setState`. The function will receive the previous value, and return an updated value. Here's an example of a counter component that uses both forms of `setState`: ```js function Counter({initialCount}) { const [count, setCount] = useState(initialCount); return ( <> Count: {count} ); } ``` The "+" and "-" buttons use the functional form, because the updated value is based on the previous value. But the "Reset" button uses the normal form, because it always sets the count back to 0. > Note > > Unlike the `setState` method found in class components, `useState` does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax: > > ```js > setState(prevState => { > // Object.assign would also work > return {...prevState, ...updatedValues}; > }); > ``` > > Another option is `useReducer`, which is more suited for managing state objects that contain multiple sub-values. #### Lazy initial state {#lazy-initial-state} The `initialState` argument is the state used during the initial render. In subsequent renders, it is disregarded. If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render: ```js const [state, setState] = useState(() => { const initialState = someExpensiveComputation(props); return initialState; }); ``` #### Bailing out of a state update {#bailing-out-of-a-state-update} If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects. (React uses the [`Object.is` comparison algorithm](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).) ### `useEffect` {#useeffect} ```js useEffect(didUpdate); ``` 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. Instead, use `useEffect`. The function passed to `useEffect` will run after the render is committed to the screen. Think of effects as an escape hatch from React's purely functional world into the imperative world. By default, effects run after every completed render, but you can choose to fire it [only when certain values have changed](#conditionally-firing-an-effect). #### Cleaning up an effect {#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. For example, to create a subscription: ```js 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. Additionally, if a component renders multiple times (as they typically do), the **previous effect is cleaned up before executing the next effect**. In our example, this means a new subscription is created on every update. To avoid firing an effect on every update, refer to the next section. #### Timing of effects {#timing-of-effects} Unlike `componentDidMount` and `componentDidUpdate`, the function passed to `useEffect` fires **after** layout and paint, during a deferred event. This makes it suitable for the many common side effects, like setting up subscriptions and event handlers, because most types of work shouldn't block the browser from updating the screen. However, not all effects can be deferred. For example, a DOM mutation that is visible to the user must fire synchronously before the next paint so that the user does not perceive a visual inconsistency. (The distinction is conceptually similar to passive versus active event listeners.) For these types of effects, React provides one additional Hook called [`useLayoutEffect`](#uselayouteffect). It has the same signature as `useEffect`, and only differs in when it is fired. Although `useEffect` is deferred until after the browser has painted, it's guaranteed to fire before any new renders. React will always flush a previous render's effects before starting a new update. #### Conditionally firing an effect {#conditionally-firing-an-effect} 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 inputs changes. However, this may be overkill in some cases, like the subscription example from the previous section. 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. Our updated example now looks like this: ```js useEffect( () => { const subscription = props.source.subscribe(); return () => { subscription.unsubscribe(); }; }, [props.source], ); ``` Now the subscription will only be recreated when `props.source` changes. Passing in an empty array `[]` of inputs tells React that your effect doesn't depend on any values from the component, so that effect would run only on mount and clean up on unmount; it won't run on updates. > Note > > The array of inputs is not passed as arguments to the effect function. Conceptually, though, that's what they represent: every value referenced inside the effect function should also appear in the inputs array. In the future, a sufficiently advanced compiler could create this array automatically. ### `useContext` {#usecontext} ```js const context = useContext(Context); ``` Accepts a context object (the value returned from `React.createContext`) and returns the current context value, as given by the nearest context provider for the given context. When the provider updates, this Hook will trigger a rerender with the latest context value. ## Additional Hooks {#additional-hooks} The following Hooks are either variants of the basic ones from the previous section, or only needed for specific edge cases. Don't stress about learning them up front. ### `useReducer` {#usereducer} ```js const [state, dispatch] = useReducer(reducer, initialArg, init); ``` An alternative to [`useState`](#usestate). Accepts a reducer of type `(state, action) => newState`, and returns the current state paired with a `dispatch` method. (If you're familiar with Redux, you already know how this works.) `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](/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down). Here's the counter example from the [`useState`](#usestate) section, rewritten to use a reducer: ```js const initialState = {count: 0}; function reducer(state, action) { switch (action.type) { case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; default: throw new Error(); } } function Counter({initialState}) { const [state, dispatch] = useReducer(reducer, initialState); return ( <> Count: {state.count} ); } ``` #### Specifying the initial state {#specifying-the-initial-state} There’s two different ways to initialize `useReducer` state. You may choose either one depending on the use case. The simplest way to pass the initial state as a second argument: ```js{3} const [state, dispatch] = useReducer( reducer, {count: initialCount} ); ``` >Note > >React doesn’t use the `state = initialState` argument convention popularized by Redux. The initial value sometimes needs to depend on props and so is specified from the Hook call instead. If you feel strongly about this, you can call `useReducer(reducer, undefined, reducer)` to emulate the Redux behavior, but it's not encouraged. #### Lazy initialization {#lazy-initialization} You can also create the initial state lazily. To do this, you can pass an `init` function as the third argument. The initial state will be set to `init(initialArg)`. It lets you extract the logic for calculating the initial state outside the reducer. This is also handy for resetting the state later in response to an action: ```js{1-3,11-12,19,24} 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} ); } ``` #### Bailing out of a dispatch {#bailing-out-of-a-dispatch} If you return the same value from a Reducer Hook as the current state, React will bail out without rendering the children or firing effects. (React uses the [`Object.is` comparison algorithm](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).) ### `useCallback` {#usecallback} ```js const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], ); ``` Returns a [memoized](https://en.wikipedia.org/wiki/Memoization) callback. Pass an inline callback and an array of inputs. `useCallback` will return a memoized version of the callback that only changes if one of the inputs has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. `shouldComponentUpdate`). `useCallback(fn, inputs)` is equivalent to `useMemo(() => fn, inputs)`. > Note > > The array of inputs is not passed as arguments to the callback. Conceptually, though, that's what they represent: every value referenced inside the callback should also appear in the inputs array. In the future, a sufficiently advanced compiler could create this array automatically. ### `useMemo` {#usememo} ```js const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); ``` Returns a [memoized](https://en.wikipedia.org/wiki/Memoization) value. Pass a "create" function and an array of inputs. `useMemo` will only recompute the memoized value when one of the inputs has changed. This optimization helps to avoid expensive calculations on every render. Remember that the function passed to `useMemo` runs during rendering. Don't do anything there that you wouldn't normally do while rendering. For example, side effects belong in `useEffect`, not `useMemo`. If no array is provided, a new value will be computed whenever a new function instance is passed as the first argument. (With an inline function, on every render.) **You may rely on `useMemo` as a performance optimization, not as a semantic guarantee.** In the future, React may choose to "forget" some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without `useMemo` — and then add it to optimize performance. > Note > > The array of inputs is not passed as arguments to the function. Conceptually, though, that's what they represent: every value referenced inside the function should also appear in the inputs array. In the future, a sufficiently advanced compiler could create this array automatically. ### `useRef` {#useref} ```js const refContainer = useRef(initialValue); ``` `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument (`initialValue`). The returned object will persist for the full lifetime of the component. A common use case is to access a child imperatively: ```js function TextInputWithFocusButton() { const inputEl = useRef(null); const onButtonClick = () => { // `current` points to the mounted text input element inputEl.current.focus(); }; return ( <> ); } ``` Note that `useRef()` is useful for more than the `ref` attribute. It's [handy for keeping any mutable value around](/docs/hooks-faq.html#is-there-something-like-instance-variables) similar to how you'd use instance fields in classes. ### `useImperativeHandle` {#useimperativehandle} ```js useImperativeHandle(ref, createHandle, [inputs]) ``` `useImperativeHandle` customizes the instance value that is exposed to parent components when using `ref`. As always, imperative code using refs should be avoided in most cases. `useImperativeHandle` should be used with `forwardRef`: ```js function FancyInput(props, ref) { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); } })); return ; } FancyInput = forwardRef(FancyInput); ``` In this example, a parent component that renders `` would be able to call `fancyInputRef.current.focus()`. ### `useLayoutEffect` {#uselayouteffect} The signature is identical to `useEffect`, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside `useLayoutEffect` will be flushed synchronously, before the browser has a chance to paint. Prefer the standard `useEffect` when possible to avoid blocking visual updates. > Tip > > If you're migrating code from a class component, `useLayoutEffect` fires in the same phase as `componentDidMount` and `componentDidUpdate`, so if you're unsure of which effect Hook to use, it's probably the least risky. ### `useDebugValue` {#usedebugvalue} ```js useDebugValue(value) ``` `useDebugValue` can be used to display a label for custom hooks in React DevTools. For example, consider the `useFriendStatus` custom Hook described in ["Building Your Own Hooks"](/docs/hooks-custom.html): ```js{6-8} function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); // ... // Show a label in DevTools next to this Hook // e.g. "FriendStatus: Online" useDebugValue(isOnline ? 'Online' : 'Offline'); return isOnline; } ``` > Tip > > We don't recommend adding debug values to every custom Hook. It's most valuable for custom Hooks that are part of shared libraries. #### Defer formatting debug values {#defer-formatting-debug-values} In some cases formatting a value for display might be an expensive operation. It's also unnecessary unless a Hook is actually inspected. For this reason `useDebugValue` accepts a formatting function as an optional second parameter. This function is only called if the Hooks are inspected. It receives the debug value as a parameter and should return a formatted display value. For example a custom Hook that returned a `Date` value could avoid calling the `toDateString` function unnecessarily by passing the following formatter: ```js useDebugValue(date, date => date.toDateString()); ```