美文网首页JavaScript
[JavaScript] 拆分Redux

[JavaScript] 拆分Redux

作者: 何幻 | 来源:发表于2016-08-22 14:56 被阅读111次

Redux是用来管理程序状态的工具,它提供了一些高阶函数让功能越来越丰富。

1. 用reducer根据action对state进行变换:
reducer(state,action)

// type Action = {Type, Value}
// type ActionCreator = Value -> Action
// actionCreator :: ActionCreator
const actionCreator = v => ({
    type: 'ADD1',
    v
})

// type Reducer = (State, Action) -> State
// reducer :: Reducer
const reducer = (state, action) => {
    switch (action.type) {
        case 'ADD1':
            return state + 1

        default:
            return state
    }
}

// testcase
const initialState = 1
const action = actionCreator(initialState)
const state = reducer(initialState, action)
console.assert(state === 2)

2. 用store保存state,store处理action之后改变状态:
store.dispatch(action)

// type Action = {Type, Value}
// type ActionCreator = Value -> Action
// actionCreator :: ActionCreator
const actionCreator = v => ({
    type: 'ADD1',
    v
})

// type Reducer = (State, Action) -> State
// reducer :: Reducer
const reducer = (state, action) => {
    switch (action.type) {
        case 'ADD1':
            return state + 1

        default:
            return state
    }
}

// type Listener = (State, Action) -> ()
// type GetState = () -> State
// type Subscribe = Listener -> ()
// type Dispatch = Action -> ()
// type Store = {GetState, Subscribe, Dispatch}
// type CreateStore = (Reducer, State) -> Store
// createStore :: CreateStore
const createStore = (reducer, initialState) => {
    let state = initialState,
        listenerList = []

    return {
        getState: () => state,
        subscribe: listener => {
            listenerList.push(listener)
        },
        dispatch: action => {
            listenerList.forEach(listener => listener(state, action))
            state = reducer(state, action)
        }
    }
}

// testcase
const initialState = 1
const store = createStore(reducer, initialState)
console.assert(store.getState() === 1)

const action = actionCreator(initialState)
const listener = (state, action) => {
    console.assert(state === 1)
    console.assert(action.type === 'ADD1')
}
store.subscribe(listener)
store.dispatch(action)
console.assert(store.getState() === 2)

3. 用bindActionCreator得到可根据当前state直接修改store的sideEffectAction:
sideEffectAction(initialState)

// type Action = {Type, Value}
// type ActionCreator = Value -> Action
// actionCreator :: ActionCreator
const actionCreator = v => ({
    type: 'ADD1',
    v
})

// type Reducer = (State, Action) -> State
// reducer :: Reducer
const reducer = (state, action) => {
    switch (action.type) {
        case 'ADD1':
            return state + 1

        default:
            return state
    }
}

// type Listener = (State, Action) -> ()
// type GetState = () -> State
// type Subscribe = Listener -> ()
// type Dispatch = Action -> ()
// type Store = {GetState, Subscribe, Dispatch}
// type CreateStore = (Reducer, State) -> Store
// createStore :: CreateStore
const createStore = (reducer, initialState) => {
    let state = initialState,
        listenerList = []

    return {
        getState: () => state,
        subscribe: listener => {
            listenerList.push(listener)
        },
        dispatch: action => {
            listenerList.forEach(listener => listener(state, action))
            state = reducer(state, action)
        }
    }
}

// bindActionCreator :: (ActionCreator, Dispatch) -> State -> ()
const bindActionCreator = (actionCreator, dispatch) => initialState => dispatch(actionCreator(initialState))

// testcase
const initialState = 1
const store = createStore(reducer, initialState)
const sideEffectAction = bindActionCreator(actionCreator, store.dispatch)
sideEffectAction(initialState)
console.assert(store.getState() === 2)

4. 用applyMiddleware加强createStore,提高store处理action的能力:
storeWithMiddleware.dispatch(action)

// type Action = {Type, Value}
// type ActionCreator = Value -> Action
// actionCreator :: ActionCreator
const actionCreator = v => ({
    type: 'ADD1',
    v
})

// type Reducer = (State, Action) -> State
// reducer :: Reducer
const reducer = (state, action) => {
    switch (action.type) {
        case 'ADD1':
            return state + 1

        default:
            return state
    }
}

// type Listener = (State, Action) -> ()
// type GetState = () -> State
// type Subscribe = Listener -> ()
// type Dispatch = Action -> ()
// type Store = {GetState, Subscribe, Dispatch}
// type CreateStore = (Reducer, State) -> Store
// createStore :: CreateStore
const createStore = (reducer, initialState) => {
    let state = initialState,
        listenerList = []

    return {
        getState: () => state,
        subscribe: listener => {
            listenerList.push(listener)
        },
        dispatch: action => {
            listenerList.forEach(listener => listener(state, action))
            state = reducer(state, action)
        }
    }
}

// compose :: [t -> t] -> (t -> t)
const compose = (...fns) => {
    let last = fns.pop()
    return (...args) => fns.reduceRight((memo, fn) => fn(memo), last(...args))
}

// type Next = Dispatch
// type Middleware = {GetState, Dispatch} -> Next -> Dispatch
// middleware :: Middleware
const middleware = ({ getState, dispatch }) => next => action => {

    // for example: 
    return next(action)
}

// applyMiddleware :: [Middleware] -> CreateStore -> CreateStore
const applyMiddleware = (...middlewares) => createStore => (reducer, initialState) => {
    let store = createStore(reducer, initialState),
        dispatch = store.dispatch,

        // chain :: [Next -> Dispatch]
        chain = middlewares.map(middleware => middleware({
            getState: store.getState,
            dispatch: action => dispatch(action)
        }))

    dispatch = compose(...chain)(dispatch)

    return {
        getState: store.getState,
        subscribe: store.subscribe,
        dispatch
    }
}

// testcase
const initialState = 1
const createStoreWithMiddleware = applyMiddleware(middleware)(createStore)
const store = createStoreWithMiddleware(reducer, initialState)
const action = actionCreator(initialState)
const listener = (state, action) => {
    console.assert(state === 1)
    console.assert(action.type === 'ADD1')
}
store.subscribe(listener)
store.dispatch(action)
console.assert(store.getState() === 2)

参考
GitHub: reactjs/redux
深入到源码:解读 redux 的设计思路与用法

相关文章

  • [JavaScript] 拆分Redux

    Redux是用来管理程序状态的工具,它提供了一些高阶函数让功能越来越丰富。 1. 用reducer根据action...

  • redux 总结

    redux redux概念 Redux是JavaScript应用程序的可预测状态容器。 redux 设计思想 We...

  • redux基础入门

    什么是redux? Redux官方文档对Redux的定义:Redux是针对JavaScript应用的可预测状态容器...

  • React实战之Redux

    Redux、React-Redux 简介 Redux 是 JavaScript 状态容器,提供可预测化的状态管理。...

  • redux之combineReducers使用介绍

    前言 redux的combineReducers()可以方便的将redux的reducer拆分为各个小的reduc...

  • SwiftUI 中使用 Redux 设计模式

    什么是Redux ?Redux 是 JavaScript 状态容器,提供可预测化的状态管理 Redux的工作原理 ...

  • redux

    Redux Redux 是JavaScript状态的容器,提供可预测化的状态管理 Redux不是React必须的,...

  • redux 浅析

    什么是 Redux Redux 是 JavaScript 状态容器,提供可预测化的状态管理。 Redux 是如何工...

  • Redux 仓库拆分

    构建一个项目时,一个仓库组件往往放不了那么多数据,并且后期很难管理,不易维护,仓库拆分可以将仓库数据以模块化的形式...

  • 【翻译】Redux 教程

    原文地址:Leveling Up with React: Redux Redux 是一个用于 JavaScript...

网友评论

    本文标题:[JavaScript] 拆分Redux

    本文链接:https://www.haomeiwen.com/subject/ynfgsttx.html