1112
</>,
1113
);
1114
});
1115
+
1116
+ // @gate enableAsyncActions
1117
+ test('useOptimistic can update repeatedly in the same async action', async () => {
1118
+ let startTransition;
1119
+ let setLoadingProgress;
1120
+ let setText;
1121
+ function App() {
1122
+ const [, _startTransition] = useTransition();
1123
+ const [text, _setText] = useState('A');
1124
+ const [loadingProgress, _setLoadingProgress] = useOptimistic(0);
1125
+ startTransition = _startTransition;
1126
+ setText = _setText;
1127
+ setLoadingProgress = _setLoadingProgress;
1128
+
1129
+ return (
1130
+ <>
1131
+ {loadingProgress !== 0 ? (
1132
+ <div key="progress">
1133
+ <Text text={`Loading... (${loadingProgress})`} />
1134
+ </div>
1135
+ ) : null}
1136
+ <div key="real">
1137
+ <Text text={text} />
1138
+ </div>
1139
+ </>
1140
+ );
1141
+ }
1142
+
1143
+ // Initial render
1144
+ const root = ReactNoop.createRoot();
1145
+ await act(() => root.render(<App text="A" />));
1146
+ assertLog(['A']);
1147
+ expect(root).toMatchRenderedOutput(<div>A</div>);
1148
+
1149
+ await act(async () => {
1150
+ startTransition(async () => {
1151
+ setLoadingProgress('25%');
1152
+ await getText('Wait 1');
1153
+ setLoadingProgress('75%');
1154
+ await getText('Wait 2');
1155
+ startTransition(() => setText('B'));
1156
+ });
1157
+ });
1158
+ assertLog(['Loading... (25%)', 'A']);
1159
+ expect(root).toMatchRenderedOutput(
1160
+ <>
1161
+ <div>Loading... (25%)</div>
1162
+ <div>A</div>
1163
+ </>,
1164
+ );
1165
+
1166
+ await act(() => resolveText('Wait 1'));
1167
+ assertLog(['Loading... (75%)', 'A']);
1168
+ expect(root).toMatchRenderedOutput(
1169
+ <>
1170
+ <div>Loading... (75%)</div>
1171
+ <div>A</div>
1172
+ </>,
1173
+ );
1174
+
1175
+ await act(() => resolveText('Wait 2'));
1176
+ assertLog(['B']);
1177
+ });
1178
});