From 6af59e959b1055dbf3c4a69ef00f5d9fa59dc7ed Mon Sep 17 00:00:00 2001 From: areschen Date: Thu, 9 May 2019 11:18:47 +0800 Subject: [PATCH 1/2] chore: use useRef to save state make async action to get current state --- src/createReducer.ts | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/createReducer.ts b/src/createReducer.ts index 7ff5fd3b83..f68a3f7f06 100644 --- a/src/createReducer.ts +++ b/src/createReducer.ts @@ -1,35 +1,37 @@ -import { useReducer } from 'react'; +import { useMemo, useRef, useState } from 'react'; -function compose(...funcs) { - if (funcs.length === 0) { - return arg => arg; - } - - if (funcs.length === 1) { - return funcs[0]; - } - - return funcs.reduce((a, b) => (...args) => a(b(...args))); +function composeMiddleware(chain) { + return (context, dispatch) => { + return chain.reduceRight((res, middleware) => { + return middleware(context)(res); + }, dispatch); + }; } -const createReducer = (...middlewares) => (...args) => { - const [state, dispatch] = useReducer(...args); - +const createReducer = (...middlewares) => (reducer, initialState, initializer = value => value) => { + const ref = useRef({}) + const [hooksState, setState] = useState(initializer(initialState)) + ref.current = hooksState let middlewareDispatch = () => { throw new Error( 'Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.' ); }; - + const dispatch = action => { + ref.current = reducer(ref.current, action) + setState(ref.current) + return action; + } + const composedMiddleware = useMemo(() => { + return composeMiddleware(middlewares); + }, middlewares); const middlewareAPI = { - getState: () => state, + getState: () => ref.current, dispatch: (...args) => middlewareDispatch(...args), }; - const chain = middlewares.map(middleware => middleware(middlewareAPI)); - middlewareDispatch = compose(...chain)(dispatch); - - return [state, middlewareDispatch]; + middlewareDispatch = composedMiddleware(middlewareAPI, dispatch); + return [ref.current, middlewareDispatch]; }; export default createReducer; From 2c1a67188a88dab36e00c7f9c3a3b3af4ed7c91f Mon Sep 17 00:00:00 2001 From: areschen Date: Thu, 9 May 2019 11:30:57 +0800 Subject: [PATCH 2/2] refactor: move initialState to useRef --- src/createReducer.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/createReducer.ts b/src/createReducer.ts index f68a3f7f06..749edfb11c 100644 --- a/src/createReducer.ts +++ b/src/createReducer.ts @@ -9,9 +9,8 @@ function composeMiddleware(chain) { } const createReducer = (...middlewares) => (reducer, initialState, initializer = value => value) => { - const ref = useRef({}) - const [hooksState, setState] = useState(initializer(initialState)) - ref.current = hooksState + const ref = useRef(initializer(initialState)) + const [, setState] = useState(ref.current) let middlewareDispatch = () => { throw new Error( 'Dispatching while constructing your middleware is not allowed. ' +