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:

the replay december 10

The Replay (12/10/25): Fixing AI code, over-engineering JavaScript, and more

Fixing AI code, over-engineering JavaScript, and more: discover what’s new in The Replay, LogRocket’s newsletter for dev and engineering leaders, in the December 10th issue.

Matt MacCormack
Dec 10, 2025 ⋅ 33 sec read

How to use TOON to reduce your token usage by 60%

TOON is a lightweight format designed to reduce token usage in LLM prompts. This post breaks down how it compares to JSON, where the savings come from, and when it actually helps.

Rosario De Chiara
Dec 10, 2025 ⋅ 5 min read
Fixing AI Generated Code

Fixing AI-generated code: 5 ways to debug, test, and ship safely

Andrew Evans, principal engineer and tech lead at CarMax discusses five ways to fix AI-generated code and help you debug, test, and ship safely.

Andrew Evans
Dec 10, 2025 ⋅ 9 min read
Apple Liquid Glass LogRocket

How to create Liquid Glass effects with CSS and SVG

This tutorial walks through recreating Apple’s Liquid Glass UI on the web using SVG filters, CSS, and React. You’ll learn how to build refraction and reflection effects with custom displacement and specular maps, and how to balance performance and accessibility when using advanced filter pipelines.

Rahul Chhodde
Dec 8, 2025 ⋅ 10 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

Hey there, want to help make our blog better?

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