Skip to content

Commit

Permalink
Bugfix: useFormState queues actions in wrong order (facebook#27570)
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
acdlite authored and AndyPengc12 committed Apr 15, 2024
1 parent 4f4d8a4 commit eb35b8b
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
31 changes: 30 additions & 1 deletion packages/react-dom/src/__tests__/ReactDOMForm-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ describe('ReactDOMForm', () => {
const thenable = record.value;
record.status = 'resolved';
record.value = text;
thenable.pings.forEach(t => t());
thenable.pings.forEach(t => t(text));
}
}

Expand Down Expand Up @@ -1082,6 +1082,35 @@ describe('ReactDOMForm', () => {
});
});

// @gate enableFormActions
// @gate enableAsyncActions
test('queues multiple actions and runs them in order', async () => {
let action;
function App() {
const [state, dispatch] = useFormState(
async (s, a) => await getText(a),
'A',
);
action = dispatch;
return <Text text={state} />;
}

const root = ReactDOMClient.createRoot(container);
await act(() => root.render(<App />));
assertLog(['A']);

await act(() => action('B'));
await act(() => action('C'));
await act(() => action('D'));

await act(() => resolveText('B'));
await act(() => resolveText('C'));
await act(() => resolveText('D'));

assertLog(['D']);
expect(container.textContent).toBe('D');
});

// @gate enableFormActions
// @gate enableAsyncActions
test('useFormState: warns if action is not async', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-reconciler/src/ReactFiberHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -1915,7 +1915,7 @@ function dispatchFormState<S, P>(
payload,
next: first,
};
last.next = newLast;
actionQueue.pending = last.next = newLast;
}
}

Expand Down

0 comments on commit eb35b8b

Please sign in to comment.