Skip to content

Commit

Permalink
Improve Reducer Hook's lazy init API (#14723)
Browse files Browse the repository at this point in the history
* Improve Reducer Hook's lazy init API

* Use generic type for initilizer input

Still requires an `any` cast in the case where `init` function is
not provided.
  • Loading branch information
acdlite authored Jan 30, 2019
1 parent fe67c16 commit f50d8fc
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 26 deletions.
19 changes: 11 additions & 8 deletions src/ReactShallowRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,10 @@ class ReactShallowRenderer {
}

_createDispatcher(): DispatcherType {
const useReducer = <S, A>(
const useReducer = <S, I, A>(
reducer: (S, A) => S,
initialState: S,
initialAction: A | void | null,
initialArg: I,
init?: I => S,
): [S, Dispatch<A>] => {
this._validateCurrentlyRenderingComponent();
this._createWorkInProgressHook();
Expand Down Expand Up @@ -259,13 +259,16 @@ class ReactShallowRenderer {
}
return [workInProgressHook.memoizedState, dispatch];
} else {
let initialState;
if (reducer === basicStateReducer) {
// Special case for `useState`.
if (typeof initialState === 'function') {
initialState = initialState();
}
} else if (initialAction !== undefined && initialAction !== null) {
initialState = reducer(initialState, initialAction);
initialState =
typeof initialArg === 'function'
? ((initialArg: any): () => S)()
: ((initialArg: any): S);
} else {
initialState =
init !== undefined ? init(initialArg) : ((initialArg: any): S);
}
workInProgressHook.memoizedState = initialState;
const queue: UpdateQueue<A> = (workInProgressHook.queue = {
Expand Down
26 changes: 8 additions & 18 deletions src/__tests__/ReactShallowRendererHooks-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,23 +91,19 @@ describe('ReactShallowRenderer with hooks', () => {
});

it('should work with useReducer', () => {
const initialState = {count: 0};

function reducer(state, action) {
switch (action.type) {
case 'reset':
return initialState;
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
return state;
}
}

function SomeComponent({initialCount}) {
const [state] = React.useReducer(reducer, {count: initialCount});
function SomeComponent(props) {
const [state] = React.useReducer(reducer, props, p => ({
count: p.initialCount,
}));

return (
<div>
Expand Down Expand Up @@ -141,25 +137,19 @@ describe('ReactShallowRenderer with hooks', () => {
});

it('should work with a dispatched state change for a useReducer', () => {
const initialState = {count: 0};

function reducer(state, action) {
switch (action.type) {
case 'reset':
return initialState;
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
return state;
}
}

function SomeComponent({initialCount}) {
const [state, dispatch] = React.useReducer(reducer, {
count: initialCount,
});
function SomeComponent(props) {
const [state, dispatch] = React.useReducer(reducer, props, p => ({
count: p.initialCount,
}));

if (state.count === 0) {
dispatch({type: 'increment'});
Expand Down

0 comments on commit f50d8fc

Please sign in to comment.