2024-10-08
3593
#react
Esteban Herrera
395
Oct 8, 2024 ⋅ 12 min read

useState in React: A complete guide

Esteban Herrera Family man. Java and JavaScript developer. Swift and VR/AR hobbyist. Like books, movies, and still trying many things. Find me at eherrera.net

Recent posts:

lewis angular signal forms

Signal Forms: Angular’s best quality of life update in years

Signal Forms in Angular 21 replace FormGroup pain and ControlValueAccessor complexity with a cleaner, reactive model built on signals.

Lewis Cianci
Feb 25, 2026 ⋅ 10 min read
replay 2 25 26

The Replay (2/25/26): Signal Forms, Ralph to the rescue, and more

Discover what’s new in The Replay, LogRocket’s newsletter for dev and engineering leaders, in the February 25th issue.

Matt MacCormack
Feb 25, 2026 ⋅ 32 sec read

Google & Shopify’s UCP: How AI agents sell online

Explore how the Universal Commerce Protocol (UCP) allows AI agents to connect with merchants, handle checkout sessions, and securely process payments in real-world e-commerce flows.

Emmanuel John
Feb 24, 2026 ⋅ 8 min read
6 React Server Component performance pitfalls in Next.js

6 React Server Component performance pitfalls in Next.js

React Server Components and the Next.js App Router enable streaming and smaller client bundles, but only when used correctly. This article explores six common mistakes that block streaming, bloat hydration, and create stale UI in production.

Temitope Oyedele
Feb 23, 2026 ⋅ 13 min read
View all posts

16 Replies to "<code>useState</code> in React: A complete guide"

  1. Thanks for a great article. By the way, I don’t think this part of the article true.

    > If you use the same value as the current state (React uses the Object.is for comparing) to update the state, React won’t trigger a re-render

    https://codesandbox.io/embed/react-hooks-playground-cfhle
    As you can check in this CodeSandBox, even when I call the state updater with the same value as the current state, it still re-renders the component.

  2. Hi Alan, you’re right, it’s not completely true. From the documentation:
    > 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.)
    > Note that React may still need to render that specific component again before bailing out. That shouldn’t be a concern because React won’t unnecessarily go ‘deeper’ into the tree.

    So it doesn’t always skip the rendering. I’ll update this part of the article. Thank you so much!

  3. This is likely a very elementary, basic JS question, but I’m learning.

    Why did you pass the anonymous function that returns the result of expensiveComputation into useState… instead of just passing the result of expensiveComputation itself?

    In this line:
    const messageState = useState( () => expensiveComputation() );

    Thank you. Once again I know this isn’t a react question but a JS question. Thank you for the clarification. My newbie skills will thank you!

    1. the argument is evaluated every time the component is re-rendered. If you pass the result of expensiveComputation directly, it will be recalculated on every render, which can lead to performance issues.

  4. I can see why a call to useState() shouldn’t be mixed into branching code (ifs, loops etc), because the identity of the state is dictated by the order of useState() calls within the stateless function call.

    However, I can’t see why having calls to the setMessage function in branching code below would be a problem (as per your example code quoted below).

    That’s because once the setMessage reference has been created, the association between the function and the specific state hook has been established, and any call to setMessage or setList will manipulate the correct value.

    In fact I don’t think hooks could work at all if the order of state hook _setting_ calls had to be predictable, so I don’t think there’s anything wrong with the code example.

    By contrast if the useState() call was conditionally called (e.g. based on props), then any state established by a later useState call would have an unpredictable identity on the second render.

    const [message, setMessage] = useState( ” );
    const [list, setList] = useState( [] );
    if (condition) {
    setMessage( aMessage ); // Sometimes it will be executed, making the order change
    }
    setList( [1, 2, 3] );

  5. Hi Cefn. Sorry for the late response, you are right, that was a bad example, I have updated the sample code to place the call to useState inside the if block. Thank you so much!

  6. Hi SpidaFly, sorry for the late response, and no problem at all answering your question. If we have an expression like this:
    let result = expensiveComputation();

    It will be evaluated immediately, blocking the execution of the code until the method returns.

    On the other hand, something like this:
    let result = () => expensiveComputation();

    Returns a function that is not executed when the line is evaluated, so the execution of the code is not blocked at that particular time. The function is executed only when you can it ( result() ), if ever. That’s the benefit of laziness (https://en.wikipedia.org/wiki/Lazy_evaluation).

    Hope this answers your question!

  7. Hi
    There is a typo in the name of useState function in the following line:

    “This article is a guide to the useSate (state) hook, the equivalent of this.state/this.setSate for functional components.|

  8. Hey Alan,

    It seems that the initial statement made in the article is true in v16.8.0 and above. I changed the react version in your CodeSandBox and true enough, React doesn’t seem to trigger a re-render if the value is the same as the current state.

  9. {
    const val = e.target.value;
    setMessage(prev => prev + val)
    } }
    />

    In this, I do not seem to understand how “prev” refers to the ACTUAL PREVIOUS value of input ??

  10. Thanks for the great article!
    I have a question about the ‘here’s how you’d update the author field of the state object’ section.
    Should this not be
    setMessageObj((prevState) => ({
    …prevState, // copy all other field/objects
    author: “Joe” // overwrite the value of the field to update
    }))

    As far as I understant, if the message child object has not changed, we can use the spread operator to copy all values as-is, then we just overwrite the author field on the top level of the state object.

  11. Thanks for the extremely helpful article!
    “If you use the previous value to update state, you must pass a function that receives the previous value and returns the new value”
    Not really, in the example given, setMessage(message + val) will work. But because message will only change after next rerender, if you call setMessage(message + val) multiple times, only one will work, and in that case you need the callback to do the trick

  12. As far as I understant, if the message child object has not changed, we can use the spread operator to copy all values as-is, then we just overwrite the author field on the top level of the state object.

  13. I’m not sure if I agree with this statement:

    “The initial value will be assigned only on the initial render. If it’s a function, it will be executed only on the initial render. In subsequent renders (due to a change of state in the component or a parent component), the argument of the useState Hook will be ignored, and the current value will be retrieved.”

    I’m currently working on a project where I’ve submitted the following changes because the dropdown value wasn’t updating after selection of a new value:

    https://github.com/MorpheusAIs/Lite-Client/pull/66/files

    After applying this change and testing out he new code the dropdown value now changes after selecting a different value from it. So it seems like the variable selectedNetwork is automatically updated when the chainId changes without having to run a useEffect function or even a setSelectedNetwork function anywhere.

Leave a Reply

Would you be interested in joining LogRocket's developer community?

Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

Sign up now