Skip to content

Commit 1055b1e

Browse files
committed
Bugfix: useFormState queues actions in wrong order
I neglected to update the "last" pointer of the action queue. Since the queue is circular, rather than dropping the update, the effect was to add the update to the front of the queue instead of the back. I didn't notice earlier because in my demos/tests, the actions would either resolve really quickly or the actions weren't order dependent (like incrementing a counter).
1 parent 779d593 commit 1055b1e

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

packages/react-dom/src/__tests__/ReactDOMForm-test.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ describe('ReactDOMForm', () => {
9090
const thenable = record.value;
9191
record.status = 'resolved';
9292
record.value = text;
93-
thenable.pings.forEach(t => t());
93+
thenable.pings.forEach(t => t(text));
9494
}
9595
}
9696

@@ -1082,6 +1082,35 @@ describe('ReactDOMForm', () => {
10821082
});
10831083
});
10841084

1085+
// @gate enableFormActions
1086+
// @gate enableAsyncActions
1087+
test('queues multiple actions and runs them in order', async () => {
1088+
let action;
1089+
function App() {
1090+
const [state, dispatch] = useFormState(
1091+
async (s, a) => await getText(a),
1092+
'A',
1093+
);
1094+
action = dispatch;
1095+
return <Text text={state} />;
1096+
}
1097+
1098+
const root = ReactDOMClient.createRoot(container);
1099+
await act(() => root.render(<App />));
1100+
assertLog(['A']);
1101+
1102+
await act(() => action('B'));
1103+
await act(() => action('C'));
1104+
await act(() => action('D'));
1105+
1106+
await act(() => resolveText('B'));
1107+
await act(() => resolveText('C'));
1108+
await act(() => resolveText('D'));
1109+
1110+
assertLog(['D']);
1111+
expect(container.textContent).toBe('D');
1112+
});
1113+
10851114
// @gate enableFormActions
10861115
// @gate enableAsyncActions
10871116
test('useFormState: warns if action is not async', async () => {

packages/react-reconciler/src/ReactFiberHooks.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1915,7 +1915,7 @@ function dispatchFormState<S, P>(
19151915
payload,
19161916
next: first,
19171917
};
1918-
last.next = newLast;
1918+
actionQueue.pending = last.next = newLast;
19191919
}
19201920
}
19211921

0 commit comments

Comments
 (0)