【问题标题】:Redux: Distinguish objects in reducersRedux:区分减速器中的对象
【发布时间】:2016-10-20 22:35:50
【问题描述】:

我对 Redux 很陌生,据我了解,应该为每种类型的对象创建一个 reducer。例如。对于用户交互,应该创建一个用户减速器。 我的问题是:您如何处理需要对象用于不同目的的情况?

场景:想象有一个返回当前用户的用户reducer。整个应用程序都需要此用户,并且每个页面上的一般控件都需要此用户。

现在,当您需要加载另一个用于不同目的的用户时会发生什么。例如。个人资料页面:加载用户以显示信息。

在这种情况下,如果使用用户 reducer,就会发生冲突。在 Redux 中处理这个问题的正确方法是什么?如果必须创建不同的 reducer,新的 reducer 的命名约定是什么?

【问题讨论】:

  • reducer 用于对状态树的一部分进行建模。因此,对于您的用户示例,您可以在状态树上有一个 users 节点(与页面类型无关),并且您的减速器从该集合中更新/添加/删除项目。然后,您的智能组件可以为不同的上下文加载该用户对象(使用 react-redux connect 从状态树中选择)。
  • 一旦您只使用一组用户,这将正常工作。如果您有多个加载不同用户集的组件,您会怎么做?这里推荐的方法是什么?

标签: reactjs redux reducers


【解决方案1】:

首先,你提到过:

加载当前用户的用户reducer

我不知道我的理解是否正确,但如果这意味着您想要(例如从 API)获取 reducer 中的当前用户,那么这是一种错误的方法。

reducer 应为 pure functions。您可以使用相同的参数多次调用它们,它们将始终返回相同的预期状态。

这样的副作用应该由action creators处理,例如:

actions/user.js

export const FETCH_ME = 'FETCH_ME'
export const FETCH_ME_SUCCESS = 'FETCH_ME_SUCCESS' 

// it's using redux-thunk (withExtraArgument: api) module to make an async action creator
export const fetchMe = () => (dispatch, getState, api) => {
  dispatch({ type: FETCH_ME })
  return api.get('/users/me').then(({ data }) => {
    dispatch({ type: FETCH_ME_SUCCESS, data })
    return data
  })
}

在您的 reducer 中,您可以简单地获取数据并设置新状态(请注意,如果您多次发送具有相同数据的操作,状态将始终相同)。

reducers/user.js

import { FETCH_ME, FETCH_ME_SUCCESS } from '../actions/user'

const initialState = {
  item: null,
  loading: false
}

export const userReducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_ME:
      return {
        ...state,
        loading: true
      }
    case FETCH_ME_SUCCESS:
      return {
        ...state,
        loading: false,
        item: action.data
      }
    default:
      return state
  }
}

现在,对于您的场景:

现在,当您需要加载另一个用于不同目的的用户时会发生什么。例如。个人资料页面:加载用户以显示信息。

您只需为此编写另一个动作创建器:

actions/user.js

export const FETCH_ME = 'FETCH_ME'
export const FETCH_ME_SUCCESS = 'FETCH_ME_SUCCESS' 
export const FETCH_USER = 'FETCH_USER'
export const FETCH_USER_SUCCESS = 'FETCH_USER_SUCCESS'

export const fetchMe = () => (dispatch, getState, api) => {
  dispatch({ type: FETCH_ME })
  return api.get('/users/me').then(({ data }) => {
    dispatch({ type: FETCH_ME_SUCCESS, data })
    return data
  })
}

export const fetchUser = (id) => (dispatch, getState, api) => {
  dispatch({ type: FETCH_USER })
  return api.get(`/users/${id}`).then(({ data }) => {
    dispatch({ type: FETCH_USER_SUCCESS, data })
    return data
  })
}

然后你调整你的 reducer 来管理更多的集合:

reducers/user.js

import { combineReducers } from 'redux'
import { FETCH_ME, FETCH_ME_SUCCESS, FETCH_USER, FETCH_USER_SUCCESS } from '../actions/user'

const initialState = {
  item: null,
  loading: false
}

const meReducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_ME:
    case FETCH_ME_SUCCESS:
      return userReducer(state, action)
    default:
      return state
  }
}

const activeReducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_USER:
    case FETCH_USER_SUCCESS:
      return userReducer(state, action)
    default:
      return state
  }
}

const userReducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_USER:
    case FETCH_ME:
      return {
        ...state,
        loading: true
      }
    case FETCH_USER_SUCCESS:
    case FETCH_ME_SUCCESS:
      return {
        ...state,
        loading: false,
        item: action.data
      }
    default:
      return state
  }
}

export default combineReducers({
  activeUser: activeReducer,
  me: meReducer
})

你的最终用户状态应该是这样的:

{
  me: {
    item: null,
    loading: false
  },
  active: {
    item: null,
    loading: false
  }
}

【讨论】:

  • 感谢您的故障,我正在将用户加载到我的操作中。在最初的描述中,这是我的错误。我会更正它,具有多个集合的减速器示例正是我想要的,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多