从另一个减速器中的一个减速器访问减速器状态的一部分

Posted

技术标签:

【中文标题】从另一个减速器中的一个减速器访问减速器状态的一部分【英文标题】:Accessing a part of reducer state from one reducer within another reducer 【发布时间】:2017-07-03 12:27:28 【问题描述】:

我不知道如何从reducerRegister.js 中的reducerForm.js 减速器访问布尔isLoading 标志。我使用combineReducers() 并使用isLoading 在表单提交期间禁用按钮。

初始状态为false,点击提交后变为true。表单提交成功后,isLoading再次重置为false。下面是这个问题的相关代码:

actionRegister.js

let _registerUserFailure = (payload) => 
    return 
        type: types.SAVE_USER_FAILURE,
        payload
    ;
;
let _registerUserSuccess = (payload) => 
    return 
        type: types.SAVE_USER_SUCCESS,
        payload,
        is_Active: 0,
        isLoading:true
    ;
;

let _hideNotification = (payload) => 
    return 
        type: types.HIDE_NOTIFICATION,
        payload: ''
    ;
;

// asynchronous helpers
export function registerUser( // use redux-thunk for asynchronous dispatch
    timezone,
    password,
    passwordConfirmation,
    email,
    name
) 
    return dispatch => 
        axios.all([axios.post('/auth/signup', 
                    timezone,
                    password,
                    passwordConfirmation,
                    email,
                    name,
                    is_Active: 0
                )
                // axios.post('/send', email)
            ])
            .then(axios.spread(res => 
                dispatch(_registerUserSuccess(res.data.message));
                dispatch(formReset());
                setTimeout(() => 
                    dispatch(_hideNotification(res.data.message));
                , 10000);
            ))
            .catch(res => 
                // BE validation and passport error message
                dispatch(_registerUserFailure(res.data.message));
                setTimeout(() => 
                    dispatch(_hideNotification(res.data.message));
                , 10000);
            );
    ;
 

actionForm.js

export function formUpdate(name, value)  
    return 
        type: types.FORM_UPDATE_VALUE,
        name, //shorthand from name:name introduced in ES2016
        value
    ;

export function formReset() 
  return 
    type: types.FORM_RESET
  ;

reducerRegister.js

const INITIAL_STATE = 
  error:,
  is_Active:false,
  isLoading:false
;
const reducerSignup = (state = INITIAL_STATE , action) => 
  switch(action.type) 
    case types.SAVE_USER_SUCCESS:
      return  ...state, is_Active:false, isLoading: true, error:  register: action.payload ;
      case types.SAVE_USER_FAILURE:
      return  ...state, error:  register: action.payload ;
      case types.HIDE_NOTIFICATION:
      return  ...state , error: ;
   
      return state;
;
export default reducerSignup;

reducerForm.js

const INITIAL_STATE = 
    values: 
;
const reducerUpdate = (state = INITIAL_STATE, action) => 
    switch (action.type) 
        case types.FORM_UPDATE_VALUE:
            return Object.assign(, state, 
                values: Object.assign(, state.values, 
                    [action.name]: action.value,
                )
            );
        case types.FORM_RESET:
        return INITIAL_STATE;
        // here I need isLoading value from reducerRegister.js
    
    return state;
;
export default reducerUpdate;

reducerCombined.js

import  combineReducers  from 'redux';
import reducerRegister from './reducerRegister';
import reducerLogin from './reducerLogin';
import reducerForm from './reducerForm';

const rootReducer = combineReducers(
  signup:reducerRegister,
  signin: reducerLogin,
  form: reducerForm
);

export default rootReducer;

这是我使用isLoading的地方:

  let isLoading = this.props.isLoading;
<FormGroup>
    <Col smOffset=4 sm=8>
     <Button type="submit"  disabled=isLoading
       onClick=!isLoading ? isLoading : null
     >
      isLoading ? 'Creating...' : 'Create New Account'
       </Button>
   </Col>
       </FormGroup>

将状态映射到同一组件内的道具

function mapStateToProps(state) 
    return 
        errorMessage: state.signup.error,
    isLoading: state.signup.isLoading,
    values: state.form.values

    ;

【问题讨论】:

【参考方案1】:

这在 https://redux.js.org/faq/reducers#how-do-i-share-state-between-two-reducers-do-i-have-to-use-combinereducers 的 Redux 常见问题解答中有所介绍:

很多用户后来想尝试在两个reducer之间共享数据,但发现combineReducers不允许他们这样做。有几种方法可以使用:

如果 reducer 需要了解来自另一个状态切片的数据,则可能需要重新组织状态树形状,以便单个 reducer 处理更多数据。 您可能需要编写一些自定义函数来处理其中一些操作。这可能需要用您自己的*** reducer 函数替换 combineReducers。您还可以使用 reduce-reducers 等实用程序来运行 combineReducers 来处理大多数操作,还可以为跨状态切片的特定操作运行更专业的 reducer。 redux-thunk 等异步操作创建者可以通过 getState() 访问整个状态。动作创建者可以从状态中检索其他数据并将其放入动作中,以便每个 reducer 都有足够的信息来更新自己的状态切片。

【讨论】:

谢谢,@markerikson,错过了文档的那部分,将阅读,但最后一种方法对我来说似乎最好使用 getState() 所以第一说如果reducer A 最终需要来自reducer B 的数据,您需要将它们合并为reducer AB,对吧? 作为一种潜在的选择,是的。【参考方案2】:

一个reducer 不能访问另一个reducer 的状态,但是如果你使用redux-thunk,你可以在action creator 中这样做。例如,您可以像这样定义一个动作创建者:

export const someAction = () =>
  (dispatch, getState) => 
    const someVal = getState().someReducer.someVal;
    dispatch( type: types.SOME_ACTION, valFromOtherReducer: someVal );
  ;

【讨论】:

【参考方案3】:

React Redux 适用于单向数据流。

Action ---> Reducer /store ---> Reducer

Reducer 适用于 store 的一小部分,您无法访问不属于 Reducer 的 reducer 内的 store。您可能需要根据减速器状态返回从组件中触发新操作。

【讨论】:

那你如何访问,我知道你可以触发一个动作来发送数据。

以上是关于从另一个减速器中的一个减速器访问减速器状态的一部分的主要内容,如果未能解决你的问题,请参考以下文章

在 Reducer 中保存设置并从另一个 Reducer 访问它们?

Hadoop MapReduce访问减速器中的映射器输出编号

如何通过 Angular 中的 NGRX 减速器使用数组更新状态?

登录到控制台而不是减速器操作中的代理对象时如何查看状态?

如何访问减速器(redux-router)中的当前位置?

从不同的减速器访问减速器?