| 356 | } |
| 357 | |
| 358 | export function useReducer<S, I, A>( |
| 359 | reducer: (S, A) => S, |
| 360 | initialArg: I, |
| 361 | init?: I => S, |
| 362 | ): [S, Dispatch<A>] { |
| 363 | if (__DEV__) { |
| 364 | if (reducer !== basicStateReducer) { |
| 365 | currentHookNameInDev = 'useReducer'; |
| 366 | } |
| 367 | } |
| 368 | currentlyRenderingComponent = resolveCurrentlyRenderingComponent(); |
| 369 | workInProgressHook = createWorkInProgressHook(); |
| 370 | if (isReRender) { |
| 371 | // This is a re-render. Apply the new render phase updates to the previous |
| 372 | // current hook. |
| 373 | const queue: UpdateQueue<A> = (workInProgressHook.queue: any); |
| 374 | const dispatch: Dispatch<A> = (queue.dispatch: any); |
| 375 | if (renderPhaseUpdates !== null) { |
| 376 | // Render phase updates are stored in a map of queue -> linked list |
| 377 | const firstRenderPhaseUpdate = renderPhaseUpdates.get(queue); |
| 378 | if (firstRenderPhaseUpdate !== undefined) { |
| 379 | // $FlowFixMe[incompatible-use] found when upgrading Flow |
| 380 | renderPhaseUpdates.delete(queue); |
| 381 | // $FlowFixMe[incompatible-use] found when upgrading Flow |
| 382 | let newState = workInProgressHook.memoizedState; |
| 383 | let update: Update<any> = firstRenderPhaseUpdate; |
| 384 | do { |
| 385 | // Process this render phase update. We don't have to check the |
| 386 | // priority because it will always be the same as the current |
| 387 | // render's. |
| 388 | const action = update.action; |
| 389 | if (__DEV__) { |
| 390 | isInHookUserCodeInDev = true; |
| 391 | } |
| 392 | newState = reducer(newState, action); |
| 393 | if (__DEV__) { |
| 394 | isInHookUserCodeInDev = false; |
| 395 | } |
| 396 | // $FlowFixMe[incompatible-type] we bail out when we get a null |
| 397 | update = update.next; |
| 398 | } while (update !== null); |
| 399 | |
| 400 | // $FlowFixMe[incompatible-use] found when upgrading Flow |
| 401 | workInProgressHook.memoizedState = newState; |
| 402 | |
| 403 | return [newState, dispatch]; |
| 404 | } |
| 405 | } |
| 406 | // $FlowFixMe[incompatible-use] found when upgrading Flow |
| 407 | return [workInProgressHook.memoizedState, dispatch]; |
| 408 | } else { |
| 409 | if (__DEV__) { |
| 410 | isInHookUserCodeInDev = true; |
| 411 | } |
| 412 | let initialState; |
| 413 | if (reducer === basicStateReducer) { |
| 414 | // Special case for `useState`. |
| 415 | initialState = |