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:

Building a Full-Featured Laravel Admin Dashboard with Filament

Building a full-featured Laravel admin dashboard with Filament

Build scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.

Kayode Adeniyi
Dec 20, 2024 â‹… 5 min read
Working With URLs In JavaScript

Working with URLs in JavaScript

Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.

Joe Attardi
Dec 19, 2024 â‹… 6 min read
Lazy Loading Vs. Eager Loading

Lazy loading vs. Eager loading

In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.

Njong Emy
Dec 18, 2024 â‹… 5 min read
Deno logo over an orange background

How to migrate your Node.js app to Deno 2.0

Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]

Yashodhan Joshi
Dec 17, 2024 â‹… 7 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