diff --git a/src/content/reference/react/useReducer.md b/src/content/reference/react/useReducer.md
index ed3dc68c2..f17b70a8a 100644
--- a/src/content/reference/react/useReducer.md
+++ b/src/content/reference/react/useReducer.md
@@ -1,353 +1,25 @@
----
-title: useReducer
----
-
-
-
-`useReducer` is a React Hook that lets you add a [reducer](/learn/extracting-state-logic-into-a-reducer) to your component.
-
-```js
-const [state, dispatch] = useReducer(reducer, initialArg, init?)
-```
-
-
-
-
-
----
-
-## Reference {/*reference*/}
-
-### `useReducer(reducer, initialArg, init?)` {/*usereducer*/}
-
-Call `useReducer` at the top level of your component to manage its state with a [reducer.](/learn/extracting-state-logic-into-a-reducer)
-
-```js
-import { useReducer } from 'react';
-
-function reducer(state, action) {
- // ...
-}
-
-function MyComponent() {
- const [state, dispatch] = useReducer(reducer, { age: 42 });
- // ...
-```
-
-[See more examples below.](#usage)
-
-#### Parameters {/*parameters*/}
-
-* `reducer`: The reducer function that specifies how the state gets updated. It must be pure, should take the state and action as arguments, and should return the next state. State and action can be of any types.
-* `initialArg`: The value from which the initial state is calculated. It can be a value of any type. How the initial state is calculated from it depends on the next `init` argument.
-* **optional** `init`: The initializer function that should return the initial state. If it's not specified, the initial state is set to `initialArg`. Otherwise, the initial state is set to the result of calling `init(initialArg)`.
-
-#### Returns {/*returns*/}
-
-`useReducer` returns an array with exactly two values:
-
-1. The current state. During the first render, it's set to `init(initialArg)` or `initialArg` (if there's no `init`).
-2. The [`dispatch` function](#dispatch) that lets you update the state to a different value and trigger a re-render.
-
-#### Caveats {/*caveats*/}
-
-* `useReducer` is a Hook, so you can only call it **at the top level of your component** or your own Hooks. You can't call it inside loops or conditions. If you need that, extract a new component and move the state into it.
-* The `dispatch` function has a stable identity, so you will often see it omitted from Effect dependencies, but including it will not cause the Effect to fire. If the linter lets you omit a dependency without errors, it is safe to do. [Learn more about removing Effect dependencies.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect)
-* In Strict Mode, React will **call your reducer and initializer twice** in order to [help you find accidental impurities.](#my-reducer-or-initializer-function-runs-twice) This is development-only behavior and does not affect production. If your reducer and initializer are pure (as they should be), this should not affect your logic. The result from one of the calls is ignored.
-
----
-
-### `dispatch` function {/*dispatch*/}
-
-The `dispatch` function returned by `useReducer` lets you update the state to a different value and trigger a re-render. You need to pass the action as the only argument to the `dispatch` function:
-
-```js
-const [state, dispatch] = useReducer(reducer, { age: 42 });
-
-function handleClick() {
- dispatch({ type: 'incremented_age' });
- // ...
-```
-
-React will set the next state to the result of calling the `reducer` function you've provided with the current `state` and the action you've passed to `dispatch`.
-
-#### Parameters {/*dispatch-parameters*/}
-
-* `action`: The action performed by the user. It can be a value of any type. By convention, an action is usually an object with a `type` property identifying it and, optionally, other properties with additional information.
-
-#### Returns {/*dispatch-returns*/}
-
-`dispatch` functions do not have a return value.
-
-#### Caveats {/*setstate-caveats*/}
-
-* The `dispatch` function **only updates the state variable for the *next* render**. If you read the state variable after calling the `dispatch` function, [you will still get the old value](#ive-dispatched-an-action-but-logging-gives-me-the-old-state-value) that was on the screen before your call.
-
-* If the new value you provide is identical to the current `state`, as determined by an [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison, React will **skip re-rendering the component and its children.** This is an optimization. React may still need to call your component before ignoring the result, but it shouldn't affect your code.
-
-* React [batches state updates.](/learn/queueing-a-series-of-state-updates) It updates the screen **after all the event handlers have run** and have called their `set` functions. This prevents multiple re-renders during a single event. In the rare case that you need to force React to update the screen earlier, for example to access the DOM, you can use [`flushSync`.](/reference/react-dom/flushSync)
-
----
-
-## Usage {/*usage*/}
-
-### Adding a reducer to a component {/*adding-a-reducer-to-a-component*/}
-
-Call `useReducer` at the top level of your component to manage state with a [reducer.](/learn/extracting-state-logic-into-a-reducer)
-
-```js [[1, 8, "state"], [2, 8, "dispatch"], [4, 8, "reducer"], [3, 8, "{ age: 42 }"]]
-import { useReducer } from 'react';
-
-function reducer(state, action) {
- // ...
-}
-
-function MyComponent() {
- const [state, dispatch] = useReducer(reducer, { age: 42 });
- // ...
-```
-
-`useReducer` returns an array with exactly two items:
-
-1. The current state of this state variable, initially set to the initial state you provided.
-2. The `dispatch` function that lets you change it in response to interaction.
-
-To update what's on the screen, call `dispatch` with an object representing what the user did, called an *action*:
-
-```js [[2, 2, "dispatch"]]
-function handleClick() {
- dispatch({ type: 'incremented_age' });
-}
-```
-
-React will pass the current state and the action to your reducer function. Your reducer will calculate and return the next state. React will store that next state, render your component with it, and update the UI.
-
-
-
-```js
-import { useReducer } from 'react';
-
-function reducer(state, action) {
- if (action.type === 'incremented_age') {
- return {
- age: state.age + 1
- };
- }
- throw Error('Unknown action.');
-}
-
-export default function Counter() {
- const [state, dispatch] = useReducer(reducer, { age: 42 });
-
- return (
- <>
-
-
- >
- );
-}
-```
-
-```css
-button { display: block; margin-top: 10px; }
-```
-
-
-
-
-
-#### Todo list (array) {/*todo-list-array*/}
-
-In this example, the reducer manages an array of tasks. The array needs to be updated [without mutation.](/learn/updating-arrays-in-state)
-
-
-
-```js src/App.js
-import { useReducer } from 'react';
+import { useImmerReducer } from 'use-immer';
import AddTask from './AddTask.js';
import TaskList from './TaskList.js';
-function tasksReducer(tasks, action) {
+function tasksReducer(draft, action) {
switch (action.type) {
case 'added': {
- return [...tasks, {
+ draft.push({
id: action.id,
text: action.text,
done: false
- }];
+ });
+ break;
}
case 'changed': {
- return tasks.map(t => {
- if (t.id === action.task.id) {
- return action.task;
- } else {
- return t;
- }
- });
+ const index = draft.findIndex(t => t.id === action.task.id);
+ draft[index] = action.task;
+ break;
}
case 'deleted': {
- return tasks.filter(t => t.id !== action.id);
+ return draft.filter(t => t.id !== action.id);
}
default: {
throw Error('Unknown action: ' + action.type);
@@ -356,7 +28,7 @@ function tasksReducer(tasks, action) {
}
export default function TaskApp() {
- const [tasks, dispatch] = useReducer(
+ const [tasks, dispatch] = useImmerReducer(
tasksReducer,
initialTasks
);
@@ -508,19 +180,127 @@ ul, li { margin: 0; padding: 0; }
-
+
+
+
+
+---
+
+### Initializing state lazily {/*initializing-state-lazily*/}
+
+You can provide the initial state as the second argument to `useReducer`:
+
+```js
+const [state, dispatch] = useReducer(reducer, { count: 0 });
+```
+
+Sometimes, calculating the initial state is expensive. You might need to make an API call, read from local storage, or perform some other computation that you might want to avoid if the component is rendering for the first time. In that case, you can provide an *initializer* function as the third argument. React will call your initializer function and use its return value as the initial state.
+
+```js
+function init(initialCount) {
+ return { count: initialCount };
+}
+
+function Counter({ initialCount }) {
+ const [state, dispatch] = useReducer(reducer, initialCount, init);
+ // ...
+```
+
+In the example above, `init(initialCount)` is only called once, during the initial render.
-#### Writing concise update logic with Immer {/*writing-concise-update-logic-with-immer*/}
+
-If updating arrays and objects without mutation feels tedious, you can use a library like [Immer](https://github.com/immerjs/use-immer#useimmerreducer) to reduce repetitive code. Immer lets you write concise code as if you were mutating objects, but under the hood it performs immutable updates:
+#### Counter with a lazy initialization {/*counter-with-a-lazy-initialization*/}
+
+In this example, the initial count is read from the `props`. Using an initializer function ensures that the `init` function is only called during the initial render, so you avoid unnecessary calculations.
-```js src/App.js
-import { useImmerReducer } from 'use-immer';
-import AddTask from './AddTask.js';
-import TaskList from './TaskList.js';
+```js
+import { useReducer } from 'react';
+
+function reducer(state, action) {
+ switch (action.type) {
+ case 'increment':
+ return { count: state.count + 1 };
+ case 'decrement':
+ return { count: state.count - 1 };
+ default:
+ throw new Error();
+ }
+}
+
+function init(initialCount) {
+ return { count: initialCount };
+}
+
+function Counter({ initialCount }) {
+ const [state, dispatch] = useReducer(reducer, initialCount, init);
+ return (
+ <>
+ Count: {state.count}
+
+
+ >
+ );
+}
+
+export default function App() {
+ return (
+
+ );
+}
+```
+
+
+
+
+
+
+
+---
+
+## Troubleshooting {/*troubleshooting*/}
+
+### My reducer or initializer function runs twice {/*my-reducer-or-initializer-function-runs-twice*/}
+
+In Strict Mode, React will call your reducer and initializer functions twice in development to [help you find accidental impurities.](/reference/react/StrictMode#how-to-enable-strict-mode) This is a development-only behavior and does not affect production.
+
+If your reducer and initializer functions are pure, this should not affect your logic. The result from one of the calls is ignored. However, if your reducer or initializer has side effects (e.g. logging, modifying the input, or mutating state), you will notice them running twice. To fix this, make sure that your reducer and initializer functions are pure.
+
+### I've dispatched an action, but logging gives me the old state value {/*ive-dispatched-an-action-but-logging-gives-me-the-old-state-value*/}
+
+Calling `dispatch` does not update the `state` variable inside the *current* execution of your component.
+```js
+function handleClick() {
+ dispatch({ type: 'incremented_age' });
+ console.log(state.age); // This will log the old state value.
+}
+```
+
+This is by design. Your component will re-render with the new state value *after* the event handler finishes running.
+
+If you need to know the next state value immediately after dispatching the action, you could calculate it manually by calling the `reducer` function directly:
+
+```js
+function handleClick() {
+ const nextState = reducer(state, { type: 'incremented_age' });
+ console.log(nextState.age); // This will log the next state value.
+ dispatch({ type: 'incremented_age' });
+}
+```
+
+However, usually you don't need to do this. React will re-render your component with the updated values in the next render.
+```js
function tasksReducer(draft, action) {
switch (action.type) {
case 'added': {
@@ -542,7 +322,7 @@ function tasksReducer(draft, action) {
return draft.filter(t => t.id !== action.id);
}
default: {
- throw Error('Unknown action: ' + action.type);
+ throw Error('Ação desconhecida: ' + action.type);
}
}
}
@@ -577,7 +357,7 @@ export default function TaskApp() {
return (
<>
-