Skip to content

Commit 3ea0999

Browse files
committed
docs: clarify when updater functions are needed for useState
The existing DeepDive overstated the guarantee that state is always up-to-date before the next user action. This is not true when the state variable has been updated inside a Transition elsewhere in the app, or when multiple updates happen in the same event handler. Restructure to present both cases together and contrast the two approaches (reading the state variable vs. using an updater).
1 parent 6ec6134 commit 3ea0999

1 file changed

Lines changed: 7 additions & 4 deletions

File tree

src/content/reference/react/useState.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,13 +320,16 @@ React may [call your updaters twice](#my-initializer-or-updater-function-runs-tw
320320
321321
#### Is using an updater always preferred? {/*is-using-an-updater-always-preferred*/}
322322
323-
You might hear a recommendation to always write code like `setAge(a => a + 1)` if the state you're setting is calculated from the previous state. There is no harm in it, but it is also not always necessary.
323+
You might hear a recommendation to always write code like `setAge(a => a + 1)` if the state you're setting is calculated from the previous state. This is generally fine, but there are some nuances to consider.
324324
325-
In most cases, there is no difference between these two approaches. React always makes sure that for intentional user actions, like clicks, the `age` state variable would be updated before the next click. This means there is no risk of a click handler seeing a "stale" `age` at the beginning of the event handler.
325+
For intentional user actions, like clicks, React always ensures that the state variable matches what was visible on the screen when the user took the action. However, if you do multiple updates within the same event handler, or if the state has been previously updated within a [Transition](/reference/react/startTransition), there may also be queued updates. In these cases you should intentionally choose how you access the previous state.
326326
327-
However, if you do multiple updates within the same event, updaters can be helpful. They're also helpful if accessing the state variable itself is inconvenient (you might run into this when optimizing re-renders).
327+
* Using the state variable `age` allows you to calculate your state based on the age the user saw when they took the action.
328+
* Using an updater `setAge(a => a + 1)` allows you to calculate your state based on the currently pending state.
328329
329-
If you prefer consistency over slightly more verbose syntax, it's reasonable to always write an updater if the state you're setting is calculated from the previous state. If it's calculated from the previous state of some *other* state variable, you might want to combine them into one object and [use a reducer.](/learn/extracting-state-logic-into-a-reducer)
330+
Updaters can also be valuable as an optimization since they let you access the state value during an update without forcing your component to re-render on every update.
331+
332+
If you prefer consistency over slightly more verbose syntax, it's a reasonable default to always write an updater if the state you're setting is calculated from the previous state. If it's calculated from the previous state of some *other* state variable, you might want to combine them into one object and [use a reducer.](/learn/extracting-state-logic-into-a-reducer)
330333
331334
</DeepDive>
332335

0 commit comments

Comments
 (0)