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:

react animation libraries 2026

Comparing the best React animation libraries for 2026

Evaluate the top React animation libraries for ease of use, developer experience, and bundle size.

Fortune Ikechi
Jan 22, 2026 ⋅ 21 min read

Why your AI agent needs a task queue (and how to build one)

AI agents fan out work across multiple LLM calls and services. Task queues add retries, ordering, and context preservation to keep these workflows reliable.

Muhammed Ali
Jan 22, 2026 ⋅ 7 min read
the replay january 21 2026

The Replay (1/21/26): Booming CSS, Tauri 2.0, and more

Discover what’s new in The Replay, LogRocket’s newsletter for dev and engineering leaders, in the January 21st issue.

Matt MacCormack
Jan 21, 2026 ⋅ 39 sec read
jemima abu css in 2026 replacing javascript

CSS in 2026: The new features reshaping frontend development

Jemima Abu, a senior product engineer and award-winning developer educator, shows how she replaced 150+ lines of JavaScript with just a few new CSS features.

Jemima Abu
Jan 21, 2026 ⋅ 6 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