You can use useEffect/useLayoutEffect to achieve this:
const SomeComponent = () => {
const [count, setCount] = React.useState(0)
React.useEffect(() => {
if (count > 1) {
document.title = 'Threshold of over 1 reached.';
} else {
document.title = 'No threshold reached.';
}
}, [count]);
return (
<div>
<p>{count}</p>
<button type="button" onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
);
};
If you want to prevent the callback from running on first render, adjust the previous version:
const SomeComponent = () => {
const [count, setCount] = React.useState(0)
const didMount = React.useRef(false);
React.useEffect(() => {
if (!didMount.current) {
didMount.current = true;
return;
}
if (count > 1) {
document.title = 'Threshold of over 1 reached.';
} else {
document.title = 'No threshold reached.';
}
}, [count]);
return (
<div>
<p>{count}</p>
<button type="button" onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
);
};
More about it over here.
Answer from Robin Wieruch on Stack OverflowReact
react.dev › reference › react › useState
useState – React
Call useState at the top level of your component to declare one or more state variables.
Top answer 1 of 8
179
You can use useEffect/useLayoutEffect to achieve this:
const SomeComponent = () => {
const [count, setCount] = React.useState(0)
React.useEffect(() => {
if (count > 1) {
document.title = 'Threshold of over 1 reached.';
} else {
document.title = 'No threshold reached.';
}
}, [count]);
return (
<div>
<p>{count}</p>
<button type="button" onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
);
};
If you want to prevent the callback from running on first render, adjust the previous version:
const SomeComponent = () => {
const [count, setCount] = React.useState(0)
const didMount = React.useRef(false);
React.useEffect(() => {
if (!didMount.current) {
didMount.current = true;
return;
}
if (count > 1) {
document.title = 'Threshold of over 1 reached.';
} else {
document.title = 'No threshold reached.';
}
}, [count]);
return (
<div>
<p>{count}</p>
<button type="button" onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
);
};
More about it over here.
2 of 8
157
setState(updater, callback) for useState
Following implementation comes really close to the original setState callback of classes.
Improvements made to accepted answer:
- Callback execution is omitted on initial render - we only want to call it on state updates
- Callback can be dynamic for each
setStateinvocation, like with classes
Usage
const App = () => {
const [state, setState] = useStateCallback(0); // same API as useState
const handleClick = () => {
setState(
prev => prev + 1,
// second argument is callback, `s` being the *updated* state
s => console.log("I am called after setState, state:", s)
);
};
return <button onClick={handleClick}>Increment</button>;
}
useStateCallback
function useStateCallback(initialState) {
const [state, setState] = useState(initialState);
const cbRef = useRef(null); // init mutable ref container for callbacks
const setStateCallback = useCallback((state, cb) => {
cbRef.current = cb; // store current, passed callback in ref
setState(state);
}, []); // keep object reference stable, exactly like `useState`
useEffect(() => {
// cb.current is `null` on initial render,
// so we only invoke callback on state *updates*
if (cbRef.current) {
cbRef.current(state);
cbRef.current = null; // reset callback after execution
}
}, [state]);
return [state, setStateCallback];
}
TypeScript version
function useStateCallback<T>(
initialState: T
): [T, (state: T, cb?: (state: T) => void) => void] {
const [state, setState] = useState(initialState);
const cbRef = useRef<((state: T) => void) | undefined>(undefined); // init mutable ref container for callbacks
const setStateCallback = useCallback((state: T, cb?: (state: T) => void) => {
cbRef.current = cb; // store current, passed callback in ref
setState(state);
}, []); // keep object reference stable, exactly like `useState`
useEffect(() => {
// cb.current is `undefined` on initial render,
// so we only invoke callback on state *updates*
if (cbRef.current) {
cbRef.current(state);
cbRef.current = undefined; // reset callback after execution
}
}, [state]);
return [state, setStateCallback];
}
Further info: React Hooks FAQ: Is there something like instance variables?
Working example
const App = () => {
const [state, setState] = useStateCallback(0);
const handleClick = () =>
setState(
prev => prev + 1,
// important: use `s`, not the stale/old closure value `state`
s => console.log("I am called after setState, state:", s)
);
return (
<div>
<p>Hello Comp. State: {state} </p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
function useStateCallback(initialState) {
const [state, setState] = useState(initialState);
const cbRef = useRef(null);
const setStateCallback = useCallback((state, cb) => {
cbRef.current = cb;
setState(state);
}, []);
useEffect(() => {
if (cbRef.current) {
cbRef.current(state);
cbRef.current = null;
}
}, [state]);
return [state, setStateCallback];
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<script>var { useReducer, useEffect, useState, useRef, useCallback } = React</script>
<div id="root"></div>
Callbacks in useState? No? This is stupid, PLEASE change my view.
I'm really frustrated right now. I'm begrudgingly making the transition to functional components instead of class components, and I'm doing so… More on reddit.com
When does the callback inside the setter function of the useState hook execute?
The React documentation describes the setter function of the useState hook as follows: React waits until all code in the event handlers has run before processing your state updates. React queues this function(callback inside the setter) ... More on github.com
useState: when to use callback
I am working on the course over useState and useEffect. I get the general premise of the topic at hand. But I caught myself wondering why the callback function is used in some occasions and not others within the state setter funcitons. setCount(prevCount => prevCount + 1) When our state setter ... More on discuss.codecademy.com
How does Javascript/React know to pass in the previous value of a stateful variable?
React keeps the actual current props and state for each component in internal data structures called "Fibers". That's how it knows what components currently exist in the component tree, and how to update them. In this case, when you pass an updater function into setState, React will eventually call const newState = updaterFunction(fiber.prevState). See my extensive post A (Mostly) Complete Guide to React Rendering Behavior to better understand how this actually works. More on reddit.com
Videos
07:38
Did You Know About The UPDATER FUNCTION in React useState? - YouTube
03:38
useState Hook with Callback function. NextJS, Typescript, Tailwind ...
Learn React Hooks: useState - Simply Explained! - YouTube
State and Callbacks Don't Mix Well in React
Learn React Hooks: useCallback - Simply Explained!
Learn useState in 8 Minutes - React Hooks Explained (2023) - YouTube
React
react.dev › reference › react › useCallback
useCallback – React
Sometimes, you might need to update state based on previous state from a memoized callback. This handleAddTodo function specifies todos as a dependency because it computes the next todos from it: function TodoList() { const [todos, setTodos] = useState([]); const handleAddTodo = useCallback((text) => { const newTodo = { id: nextId++, text }; setTodos([...todos, newTodo]); }, [todos]); // ...
Medium
maksimrv.medium.com › usestate-with-callback-d574298eb8bd
React: useState hook with callback | by Maksim Ryzhikov | Medium
November 15, 2020 - But with new “functional” oriented React where you described components using plain functions you should use `useState` hook to track internal component’s state inside function. const [state, setState] = useState(null);setState(newState, myCallback) The `setState` above would throw warning and don’t call `myCallback` because `useState` does not support callbacks and say that you should use `useEffect` for this purpose.
Reddit
reddit.com › r/reactjs › callbacks in usestate? no? this is stupid, please change my view.
r/reactjs on Reddit: Callbacks in useState? No? This is stupid, PLEASE change my view.
June 12, 2022 - That's the beauty of hooks. Whatever logic you define using useState, useEffect, yes even that mount detect etc., can be extracted into yet another hook. VSCode: right click, refactor to module scope.
React
legacy.reactjs.org › docs › hooks-reference.html
Hooks API Reference – React
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.
GitHub
github.com › the-road-to-learn-react › use-state-with-callback
GitHub - the-road-to-learn-react/use-state-with-callback: Custom hook to include a callback function for useState. · GitHub
Next.js) // import { useStateWithCallbackInstant } from 'use-state-with-callback'; const App = () => { const [count, setCount] = useStateWithCallback(0, currentCount => { console.log('render, then callback.'); console.log('otherwise use useStateWithCallbackInstant()'); if (currentCount > 1) { console.log('Threshold of over 1 reached.'); } else { console.log('No threshold reached.'); } }); // const [count, setCount] = useStateWithCallbackInstant(0, currentCount => { // console.log('render with instant callback.'); // if (currentCount > 1) { // console.log('Threshold of over 1 reached.'); // } e
Starred by 278 users
Forked by 37 users
Languages JavaScript
GitHub
github.com › reactjs › react.dev › issues › 5982
When does the callback inside the setter function of the useState hook execute? · Issue #5982 · reactjs/react.dev
April 30, 2023 - The React documentation describes the setter function of the useState hook as follows: React waits until all code in the event handlers has run before processing your state updates. React queues this function(callback inside the setter) ...
Author nelvko
Codedamn
codedamn.com › news › react js
React useState callback tutorial
September 19, 2022 - In this section, you’re going to learn about how to use a callback with the useState hook. As part of the class component, we could pass a second argument to the setState function. However, the setState function returned by theuseState hook in the functional component does not take an extra argument. In the old “class” oriented React version you could call setState and pass it as a second argument function which would be called when the state of the component would be updated.
npm
npmjs.com › package › use-state-with-callback
use-state-with-callback - npm
April 14, 2022 - Custom hook to include a callback function for useState which was previously available for setState in class components. Read more about it here. ... import * as React from 'react'; import useStateWithCallback from 'use-state-with-callback'; // Note: cannot be used on the server-side (e.g.
» npm install use-state-with-callback
Published Apr 14, 2022
Version 3.0.2
Author “Robin
DEV Community
dev.to › mubbashir10 › callback-solution-for-usestate-hook-in-react-1ni0
Callback solution for useState hook in React - DEV Community
January 2, 2025 - import React, { Component } from 'react'; class App extends Component { constructor(props) { super(props); this.state = { beer: 0, }; } updateBeerCount = value => { this.setState({ beer: value}, ()=>{ console.log('count updated!, I\'m the callback'); }); }; render() { return ( <div> <p>Try increasing the number and check your console!</p> <input type="number" value={this.state.beer} onChange={e => this.updateBeerCount(e.target.value)} /> </div> ); } } export default App;
W3Schools
w3schools.com › react › react_usecallback.asp
React useCallback Hook
The memoized callback will only change if one of these dependencies has changed. ... //Without useCallback: import React, { useState } from 'react'; import { createRoot } from 'react-dom/client'; // Child component that receives a function prop const Button = React.memo(({ onClick, text }) => { alert(`Child ${text} button rendered`); return <button onClick={onClick}>{text}</button>; }); // Parent component without useCallback function WithoutCallbackExample() { const [count1, setCount1] = useState(0); const [count2, setCount2] = useState(0); // This function is recreated on every render const
Dushkin
dushkin.tech › posts › stale_state_react
How to fix stale React useState's state in a callback | Dmitrii Dushkin blog
June 7, 2025 - export default function App() { const [isOpen, setIsOpen] = useState(false); const [state, setState] = useState(""); console.log("State's value on render =", state); // This function is created each time on every re-render // So it holds a correct state value const callbackFn = () => { console.log("State value inside callbackFn =", state); setIsOpen(false); }; const modalOptions = { onCloseStart: callbackFn, }; return ( <div className="App"> <Button onClick={() => setIsOpen(true)}>Show modal</Button> {/** Modal component from react-materialize We defined a callback which will be fired on modal close.
LinkedIn
linkedin.com › pulse › provide-callback-usestate-hook-like-setstate-saransh-kataria
Provide callback to useState hook like setState
December 17, 2020 - We will be using the same to provide callback functionality to our useState hook to make it function similar to setState. We will be making use of the dependency array of the useEffect to achieve this. If you are not familiar with it, we recommend reading our post on useEffect react hook.