Redux:区分减速器中的对象
Redux: Distinguish objects in reducers
我是 Redux 的新手,据我了解,应该为每种类型的对象创建一个 reducer。例如。对于用户交互,应该创建一个 user reducer。 我的问题是:您如何处理出于不同目的需要对象的情况?
场景: 假设有一个用户减速器,returns 当前用户。整个应用程序都需要该用户,并且每个页面上的常规控件都需要该用户。
现在当您需要加载另一个用于不同目的的用户时会发生什么。例如。个人资料页面:加载用户以显示信息。
在这种情况下,如果使用 user reducer 就会发生冲突。在 Redux 中处理这个问题的正确方法是什么?如果必须创建不同的减速器,新减速器的命名约定是什么?
首先,您提到:
a user reducer which loads the current user
我不知道我是否理解正确,但如果这意味着你想获取(例如,从 API 中)reducer 中的当前用户,这是错误的方法。
减速器旨在 pure functions。您可以使用相同的参数多次调用它们,它们将始终 return 相同的预期状态。
像这样的副作用应该由 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
}
}
现在,对于您的场景:
Now what happens when you need to load another user which is used for different purposes. E.g. profile page: loading a user to display information.
您只需为此编写另一个动作创建器:
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
})
}
然后调整减速器以管理更多集合:
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
}
}
我是 Redux 的新手,据我了解,应该为每种类型的对象创建一个 reducer。例如。对于用户交互,应该创建一个 user reducer。 我的问题是:您如何处理出于不同目的需要对象的情况?
场景: 假设有一个用户减速器,returns 当前用户。整个应用程序都需要该用户,并且每个页面上的常规控件都需要该用户。
现在当您需要加载另一个用于不同目的的用户时会发生什么。例如。个人资料页面:加载用户以显示信息。
在这种情况下,如果使用 user reducer 就会发生冲突。在 Redux 中处理这个问题的正确方法是什么?如果必须创建不同的减速器,新减速器的命名约定是什么?
首先,您提到:
a user reducer which loads the current user
我不知道我是否理解正确,但如果这意味着你想获取(例如,从 API 中)reducer 中的当前用户,这是错误的方法。
减速器旨在 pure functions。您可以使用相同的参数多次调用它们,它们将始终 return 相同的预期状态。
像这样的副作用应该由 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
}
}
现在,对于您的场景:
Now what happens when you need to load another user which is used for different purposes. E.g. profile page: loading a user to display information.
您只需为此编写另一个动作创建器:
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
})
}
然后调整减速器以管理更多集合:
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
}
}