Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,23 @@ describe('ReactDOMServerHooks', () => {
expect(domNode.textContent).toEqual('0');
});

itRenders('with default reducer state value', async render => {
function reducer(state = 0, action) {
return action === 'increment' ? state + 1 : state;
}
function Counter() {
let [count] = useReducer(reducer);
yieldValue('Render: ' + count);
return <Text text={count} />;
}

const domNode = await render(<Counter />);

expect(clearYields()).toEqual(['Render: 0', 0]);
expect(domNode.tagName).toEqual('SPAN');
expect(domNode.textContent).toEqual('0');
});

itRenders('lazy initialization with initialAction', async render => {
function reducer(state, action) {
return action === 'increment' ? state + 1 : state;
Expand Down
9 changes: 7 additions & 2 deletions packages/react-dom/src/server/ReactPartialRendererHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ export function useState<S>(
}

export function useReducer<S, A>(
reducer: (S, A) => S,
reducer: (S, A | any) => S,
initialState: S,
initialAction: A | void | null,
): [S, Dispatch<A>] {
Expand Down Expand Up @@ -277,7 +277,12 @@ export function useReducer<S, A>(
initialState = reducer(initialState, initialAction);
}
currentlyRenderingComponent = component;
workInProgressHook.memoizedState = initialState;
if (initialState === undefined) {
// use default reducer state value
workInProgressHook.memoizedState = reducer(initialState, {});
} else {
workInProgressHook.memoizedState = initialState;
}
const queue: UpdateQueue<A> = (workInProgressHook.queue = {
last: null,
dispatch: null,
Expand Down
12 changes: 10 additions & 2 deletions packages/react-reconciler/src/ReactFiberHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ export function useState<S>(
}

export function useReducer<S, A>(
reducer: (S, A) => S,
reducer: (S, A | any) => S,
initialState: S,
initialAction: A | void | null,
): [S, Dispatch<A>] {
Expand Down Expand Up @@ -557,7 +557,15 @@ export function useReducer<S, A>(
initialState = reducer(initialState, initialAction);
}
currentlyRenderingFiber = fiber;
workInProgressHook.memoizedState = workInProgressHook.baseState = initialState;
if (initialState === undefined) {
// use default reducer state value
workInProgressHook.memoizedState = workInProgressHook.baseState = reducer(
initialState,
{},
);
} else {
workInProgressHook.memoizedState = workInProgressHook.baseState = initialState;
}
queue = workInProgressHook.queue = {
last: null,
dispatch: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,44 @@ describe('ReactHooksWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('Count: -2')]);
});

it('accepts default reducer state value as initial state', () => {
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';

function reducer(state = 0, action) {
switch (action) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}

function Counter(props, ref) {
const [count, dispatch] = useReducer(reducer);
useImperativeHandle(ref, () => ({dispatch}));
return <Text text={'Count: ' + count} />;
}

Counter = forwardRef(Counter);
const counter = React.createRef(null);
ReactNoop.render(<Counter ref={counter} />);
ReactNoop.flush();
expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]);

counter.current.dispatch(INCREMENT);
ReactNoop.flush();
expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]);

counter.current.dispatch(DECREMENT);
counter.current.dispatch(DECREMENT);
counter.current.dispatch(DECREMENT);
ReactNoop.flush();
expect(ReactNoop.getChildren()).toEqual([span('Count: -2')]);
});

it('accepts an initial action', () => {
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
Expand Down