从另一个 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 获取的当前数据,这是正确的方法,或者我应该以不同的方式进行。基本上我想overwritecurrent datanew 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 函数?

在构建 R 包时从另一个 Rcpp 函数调用 Rcpp 函数

dispatch 不调用reducer React Native

M/R 程序中 map 和 reduce 任务的数量不变

如何从另一个嵌套对象构建一个新对象[重复]

从另一个类 c++ 访问 UI 元素