rc-redux-model icon indicating copy to clipboard operation
rc-redux-model copied to clipboard

如何使用 rc-redux-model 去实现数据管理

Open PDKSophia opened this issue 4 years ago • 1 comments

Code

以下是在项目中的真实使用,帮助小伙伴们更加直观的了解,以用户模块为主

原先流程

  1. 在 action 文件中定义
// 获取用户列表
export const fetchUserList = (params, callback) => {
  return {
    type: 'FETCH_USER_LIST',
    params,
    callback,
  }
}
  1. 在 saga 中监听此 action,并发起请求,请求完成,再 put 至 reducer 中
import adapter from '@/common/adapter'
import { call, put, takeLatest } from 'redux-saga/effects'

// 获取用户列表
function* fetchUserList({ params, callback }) {
  const res = yield call(adapter.callAPI, params)
  if (res.code === 0) {
    yield put({
      type: 'STORE_USER_LIST',
      data: res.data.userList,
    })
    if (callback) callback(res.data.userList)
  }
}

function* userSaga() {
  yield takeLatest('FETCH_USER_LIST', fetchUserList)
}

export default userSaga
  1. 切换至 reducers 文件中,自己写 set、merge 等逻辑
import Immutable from 'seamless-immutable'

const initialState = Immutable({
  userList: [],
})

function userReducer(state = initialState, action) {
  switch (action.type) {
    case 'STORE_USER_LIST':
      return Immutable.merge(state, 'userList', action.data)
    default:
      return state
  }
}

export default userReducer
  1. 回到组件中,import 这个 action 文件,然后去发起请求,并且通过 callback 回调,拿到请求后的数据
import * as userActions from './userAction'

class userComponent extends React.Component {
  componentDidMount() {
    this.props.dispatch(
      userActions.fetchUserList({ userStatus: 'online' }, (userList) => {
        console.log('userList: ', userList)
      })
    )
  }
}

使用了 rc-redux-model 之后的流程

  1. 在 model 文件中写所有的 action,默认给用户提供了修改 state 的 action,所以大部分情况下,你可以不用写 reducers
import Immutable from 'seamless-immutable'
import adapter from '@common/adapter'

export default {
  namespace: 'userModel',
  state: Immutable({
    userList: [],
  }),
  action: {
    // 获取用户列表
    fetchUserList: async ({ call, commit, currentAction }) => {
      const res = await call(adapter.callAPI, {
        actionName: 'FETCH_USER_LIST',
        params: currentAction.payload.params,
      })
      if (res.code === 0) {
        commit({
          type: 'userModel/setStoreLib',
          payload: {
            key: 'userList',
            values: {
              userList: res.data.userList,
            },
          },
        })
      }
      return res.data.userList || []
    },
  },
  openSeamlessImmutable: true,
}
  1. 页面中不需要引入 action 文件,直接 dispatch 这个 action 即可
class userComponent extends React.Component {
  componentDidMount() {
    this.props
      .dispatch({
        type: 'userModel/fetchUserList',
        payload: {
          params: {
            userStatus: 'online',
          },
        },
      })
      .then((userList) => {
        console.log('userList: ', userList)
      })
      .catch((err) => {
        console.log(err)
      })
  }
}

注意,记得把在引入store.createStore 的入口文件中,将 model.reducers 和 model.thunk 加上

// createStore.js
import { createStore, applyMiddleware, combineReducers } from 'redux'
import models from './models'
import RcReduxModel from 'rc-redux-model'

const reduxModel = new RcReduxModel(models)
const _rootThunk = reduxModel.thunk
const _rootReducers = reduxModel.reducers

const reducerList = combineReducers(_rootReducers)
return createStore(reducerList, applyMiddleware(_rootThunk))

PDKSophia avatar Aug 22 '20 06:08 PDKSophia

为什么上面使用的是saga,到了入口文件变成thunk中间件了?

zhangwei900808 avatar Sep 19 '20 02:09 zhangwei900808