HstarDoc icon indicating copy to clipboard operation
HstarDoc copied to clipboard

ReduxHelper

Open hstarorg opened this issue 7 years ago • 1 comments

import { connect } from 'react-redux';
import { combineReducers, createStore } from 'redux';

const reducerMap = {};

export const reduxHelper = {
  store: null, // 缓存全局store
  _isFunction(fn) {
    return typeof fn === 'function';
  },
  /**
   * 创建Reducer的辅助方法
   * @param {object} initialState  默认state
   * @param {*} reducerObj
   */
  createReducer(initialState, reducerObj) {
    return (state = initialState, action) => {
      console.log('action', action.type);
      const reducerFn = reducerObj[action.type];
      if (this._isFunction(reducerFn)) {
        return reducerFn.call(null, state, action.payload);
      }
      return state;
    };
  },

  /**
   * 创建页面
   * @param {*} pageState
   * @param {*} viewComponent
   */
  createPage(pageState, viewComponent) {
    const self = this;
    reducerMap[pageState.namespace] = this.createReducer(pageState.state, pageState.reducers);
    function mapStateToProps(state) {
      const mapState = {};
      // 绑定页面的state属性
      Object.keys(pageState.state || {}).forEach(k => (mapState[k] = (state[pageState.namespace] || {})[k]));

      // 绑定用户定义的state属性
      let newCalcState = {};
      if (self._isFunction(pageState.mapStateToProps)) {
        newCalcState = pageState.mapStateToProps(state[pageState.namespace], this.store);
      }
      return { ...mapState, ...newCalcState };
    }
    function mapDispatchToProps(dispatch) {
      const mapDispatch = {};
      Object.keys(pageState.actions || {}).forEach(k => {
        const actionFn = pageState.actions[k];
        if (self._isFunction(actionFn)) {
          mapDispatch[k] = () => {
            actionFn(dispatch);
          };
        } else {
          console.warn(`key [${k}] not a actions`);
        }
      });
      return mapDispatch;
    }
    this.store && this.store.replaceReducer(combineReducers(reducerMap));
    return connect(mapStateToProps, mapDispatchToProps)(viewComponent);
  },

  createStore() {
    function reducer(state = {}, action) {
      return state;
    }
    this.store = createStore(reducer); // combineReducers(reducerMap)
    window.AppState = this.store;
    return this.store;
  }
};

hstarorg avatar Mar 25 '18 09:03 hstarorg

简单的一个页面使用:

import { connect } from 'react-redux';
import { reduxHelper } from '../../store/reduxHelper';
import { Login } from './Login';
const types = {
  SET_USER_INFO: 'SET_USER_INFO'
};
const pageState = {
  namespace: 'loginPage',
  state: {
    user: 'xxx'
  },
  mapStateToProps(state, store) {
    return {
      abc: state.user
    };
  },
  actions: {
    // 动作,非Redux的Action
    getUserInfo(dispatch) {
      dispatch({ type: types.SET_USER_INFO, payload: { user: Math.random() } });
    },
    setUserInfo(dispatch) {
      dispatch({ type: types.SET_USER_INFO, payload: { user: 'jay' } });
    }
  },
  reducers: {
    [types.SET_USER_INFO](state, action) {
      return {
        ...state,
        ...action
      };
    }
  }
};

export default reduxHelper.createPage(pageState, Login);

hstarorg avatar Mar 25 '18 09:03 hstarorg