从另一个 reducer 中访问一个 reducer 状态
Posted
技术标签:
【中文标题】从另一个 reducer 中访问一个 reducer 状态【英文标题】:Accessing a reducer state from within another reducer 【发布时间】:2017-03-07 05:55:26 【问题描述】:我有一个reducer,当一个动作被调度时,我正在重新调整适当的状态。现在我定期调用一个 API,所以结果会一次又一次地触发一个动作。所以我想要的是,如果减速器状态已经有数据,那么另一个减速器在发送调用时不会将状态显示为正在加载。只有在第一次接收数据时,它必须保持其加载状态。我希望我能够正确解释它
这是我的代码 sn-ps
加载状态减速器
const loading = (state = false, action) =>
switch (action.type)
case 'GET_AUDIT_DATA': // here I want to return true only when there is no data available
return true
case 'GET_AUDIT_DATA_RECEIVED':
return false
case 'GET_AUDIT_DATA_ERROR':
return false
default:
return state
组合减速器
const allReducers = combineReducers(
auditData: AuditData,
auditLoading: AuditLoading,
modifiedOrders: ModifiedOrders
);
export default allReducers;
Reducer 返回由超级代理触发的操作的数据
const auditData = (state = [], action) =>
switch(action.type)
case 'GET_AUDIT_DATA_RECEIVED':
console.log(action.data);
return action.data;
case 'GET_AUDIT_DATA_ERROR':
return action.err;
default :
return state;
export default auditData;
所以最初auditData
不包含任何数据,只有在第一次成功调用后它才会返回数据。当同时调用loading state reducer
时,它应该在GET_AUDIT_DATA
操作中返回true,只有当审计数据reducer 不包含任何数据时。
还只返回从auditData
获取的当前数据,这是正确的方法,或者我应该以不同的方式进行。基本上我想overwrite
current data
和new one
。
【问题讨论】:
【参考方案1】:您可以通过 store 调用 getState()
以获取 reducer 列表和 reducer 中的当前状态。
-
将
store
导入auditLoading
(使用 store 获取值。不要改变 store)
store.getState().auditLoading
会给你auditLoading
reducer 的状态。
这种方式类似于redux-thunk
提供的回调。其中(dispatch, getState) =>
将返回给操作。
【讨论】:
在 react 16 和 redux 4 中你不能这样做你得到 => 错误:你不能在 reducer 执行时调用 store.getState()。 reducer 已经接收到状态作为参数。从顶部 reducer 向下传递,而不是从 store 中读取。【参考方案2】:最好的方法是向Loading state reducer发送一条信息,以了解其他reducer是否已经有数据。最后有:
const loading = (state = false, action) =>
switch (action.type)
case 'GET_AUDIT_DATA':
if(!action.dataAlreadyInitialized)
return true
case 'GET_AUDIT_DATA_RECEIVED':
return false
case 'GET_AUDIT_DATA_ERROR':
return false
default:
return state
您应该可以从您的操作函数访问应用程序状态并执行以下操作:
dispatch(
type:'GET_AUDIT_DATA',
dataAlreadyInitialized: appState.auditData.length > 0
);
【讨论】:
Damien 我正在从我的容器中调度一个动作,在这种情况下我如何才能访问 appState isnt react-redux 将 appState 注入到您的容器中? 我正在通过 mapStateToProps 函数使用它,是的,它现在可以工作了。谢谢 感谢达米安的帮助。我会更喜欢 redux-thunk 但考虑到我使用 superagent 来处理我的 API 请求,这真的很容易。【参考方案3】:接受的答案很好(通过操作传递数据长度),但如果它是一条被广泛使用的信息,则可能会很费力。对于可能被每个操作使用的“当前用户”之类的内容,有时还有另一种解决方案更可取。
根据 Redux 常见问题解答https://redux.js.org/faq/reducers,向 reducer 函数添加第三个参数是完全可以接受的。即:
加载状态减速器
const loading = (state = false, action, noData) =>
switch (action.type)
case 'GET_AUDIT_DATA':
return noData
case 'GET_AUDIT_DATA_RECEIVED':
return false
case 'GET_AUDIT_DATA_ERROR':
return false
default:
return state
组合减速器
不幸的是,这意味着我们必须编写代码来组合减速器,而不是使用 combineReducers 快捷方式。但这并不难,你只需调用每个 reducer 并在有任何变化时创建一个新对象:
const allReducers = (state = null, action) =>
const auditData = AuditData(state?.auditData, action);
const auditLoading = AuditLoading(state?.auditLoading, action, !state?.auditData?.length);
const modifiedOrders = ModifiedOrders(state?.modifiedOrders, action);
return (auditData !== state?.auditData ||
auditLoading !== state?.auditLoading ||
modifiedOrders !== state?.modifiedOrders) ?
auditData, auditLoading, modifiedOrders : state;
);
export default allReducers;
请注意传递给 AuditLoading 减速器的第三个参数。不需要对其他 reducer 或调用该操作的代码进行任何更改。哪个不错!
【讨论】:
【参考方案4】:import store from '../../../redux/store'
console.log(store.getState().loginReducer.accessToken)
通过这个语句我们会得到accessToken的状态
【讨论】:
以上是关于从另一个 reducer 中访问一个 reducer 状态的主要内容,如果未能解决你的问题,请参考以下文章
是否可以使用 Redux Toolkit 从另一个 reducer 函数(在同一切片内)调用 reducer 函数?
我如何在 react redux 中访问另一个 reducer 的状态。 reducer 和 store 之间的状态流