Skip to content

Commit 1b10f12

Browse files
committed
Troubleshooting updates
1 parent 58b6c16 commit 1b10f12

File tree

1 file changed

+98
-30
lines changed

1 file changed

+98
-30
lines changed

src/content/reference/react/useActionState.md

Lines changed: 98 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,24 +1379,6 @@ In this example, "Add 10" simulates an API that returns a validation error, whic
13791379
13801380
## Troubleshooting {/*troubleshooting*/}
13811381
1382-
### My Action can no longer read the submitted form data {/*action-cant-read-form-data*/}
1383-
1384-
When you use `useActionState`, the `reducerAction` receives an extra argument as its first argument: the previous or initial state. The submitted form data is therefore its second argument instead of its first.
1385-
1386-
```js
1387-
// Without useActionState
1388-
function action(formData) {
1389-
const name = formData.get('name');
1390-
}
1391-
1392-
// With useActionState
1393-
function action(prevState, formData) {
1394-
const name = formData.get('name');
1395-
}
1396-
```
1397-
1398-
---
1399-
14001382
### My `isPending` flag is not updating {/*ispending-not-updating*/}
14011383
14021384
If you're calling `dispatchAction` manually (not through an Action prop), make sure you wrap the call in [`startTransition`](/reference/react/startTransition):
@@ -1422,28 +1404,27 @@ When `dispatchAction` is passed to an Action prop, React automatically wraps it
14221404
14231405
---
14241406
1425-
### I'm getting an error: "Cannot update form state while rendering" {/*cannot-update-during-render*/}
1407+
### My Action cannot read form data {/*action-cannot-read-form-data*/}
14261408
1427-
You cannot call `dispatchAction` during render. This causes an infinite loop because calling `dispatchAction` schedules a state update, which triggers a re-render, which calls `dispatchAction` again.
1409+
When you use `useActionState`, the `reducerAction` receives an extra argument as its first argument: the previous or initial state. The submitted form data is therefore its second argument instead of its first.
14281410
14291411
```js
1430-
function MyComponent() {
1431-
const [state, dispatchAction, isPending] = useActionState(myAction, null);
1432-
1433-
// ❌ Wrong: calling dispatchAction during render
1434-
dispatchAction();
1412+
// Without useActionState
1413+
function action(formData) {
1414+
const name = formData.get('name');
1415+
}
14351416

1436-
// ...
1417+
// With useActionState
1418+
function action(prevState, formData) {
1419+
const name = formData.get('name');
14371420
}
14381421
```
14391422
1440-
Only call `dispatchAction` in response to user events (like form submissions or button clicks) or in Effects.
1441-
14421423
---
14431424
14441425
### My actions are being skipped {/*actions-skipped*/}
14451426
1446-
If you call `dispatchAction` multiple times and some of them don't run, it may be because an earlier `dispatchAction` call threw an error.
1427+
If you call `dispatchAction` multiple times and some of them don't run, it may be because an earlier `dispatchAction` call threw an error.
14471428
14481429
When a `reducerAction` throws, React skips all subsequently queued `dispatchAction` calls.
14491430
@@ -1493,4 +1474,91 @@ function MyComponent() {
14931474
}
14941475
```
14951476
1496-
Alternatively, you can add a `key` prop to the component using `useActionState` to force it to remount with fresh state.
1477+
Alternatively, you can add a `key` prop to the component using `useActionState` to force it to remount with fresh state, or a `<form>` `action` prop, which resets automatically after submission.
1478+
1479+
---
1480+
1481+
### I'm getting an error: "An async function with useActionState was called outside of a transition." {/*async-function-outside-transition*/}
1482+
1483+
A common mistake is to forget to call `dispatchAction` from inside a Transition:
1484+
1485+
<ConsoleBlockMulti>
1486+
<ConsoleLogLine level="error">
1487+
1488+
An async function with useActionState was called outside of a transition. This is likely not what you intended (for example, isPending will not update correctly). Either call the returned function inside startTransition, or pass it to an `action` or `formAction` prop.
1489+
1490+
</ConsoleLogLine>
1491+
</ConsoleBlockMulti>
1492+
1493+
1494+
This error happens because `dispatchAction` must run inside a Transition:
1495+
1496+
```js
1497+
function MyComponent() {
1498+
const [state, dispatchAction, isPending] = useActionState(myAsyncAction, null);
1499+
1500+
function handleClick() {
1501+
// ❌ Wrong: calling dispatchAction outside a Transition
1502+
dispatchAction();
1503+
}
1504+
1505+
// ...
1506+
}
1507+
```
1508+
1509+
To fix, either wrap the call in [`startTransition`](/reference/react/startTransition):
1510+
1511+
```js
1512+
import { useActionState, startTransition } from 'react';
1513+
1514+
function MyComponent() {
1515+
const [state, dispatchAction, isPending] = useActionState(myAsyncAction, null);
1516+
1517+
function handleClick() {
1518+
// ✅ Correct: wrap in startTransition
1519+
startTransition(() => {
1520+
dispatchAction();
1521+
});
1522+
}
1523+
1524+
// ...
1525+
}
1526+
```
1527+
1528+
Or pass `dispatchAction` to an Action prop, is call in a Transition:
1529+
1530+
```js
1531+
function MyComponent() {
1532+
const [state, dispatchAction, isPending] = useActionState(myAsyncAction, null);
1533+
1534+
// ✅ Correct: action prop wraps in a Transition for you
1535+
return <Button action={dispatchAction}>...</Button>;
1536+
}
1537+
```
1538+
1539+
---
1540+
1541+
### I'm getting an error: "Cannot update action state while rendering" {/*cannot-update-during-render*/}
1542+
1543+
You cannot call `dispatchAction` during render:
1544+
1545+
<ConsoleBlock level="error">
1546+
1547+
Cannot update action state while rendering.
1548+
1549+
</ConsoleBlock>
1550+
1551+
This causes an infinite loop because calling `dispatchAction` schedules a state update, which triggers a re-render, which calls `dispatchAction` again.
1552+
1553+
```js
1554+
function MyComponent() {
1555+
const [state, dispatchAction, isPending] = useActionState(myAction, null);
1556+
1557+
// ❌ Wrong: calling dispatchAction during render
1558+
dispatchAction();
1559+
1560+
// ...
1561+
}
1562+
```
1563+
1564+
To fix, only call `dispatchAction` in response to user events (like form submissions or button clicks).

0 commit comments

Comments
 (0)