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

IT技术 javascript reactjs redux react-redux reducers
2021-03-25 13:09:03

我不知道如何访问一个布尔值,isLoading从标志reducerForm.js减速在reducerRegister.js我已经使用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>

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

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

    };
}
3个回答

这在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 A最终需要来自reducer B您的数据,需要将它们合并reducer AB,对吗?
2021-05-27 13:09:03
谢谢,@markerikson,错过了文档的那部分,我会阅读,但最后一种方法对我来说似乎最好使用 getState()
2021-06-09 13:09:03
作为一种潜在的选择,是的。
2021-06-14 13:09:03

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

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

React Redux 适用于单向数据流。

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

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

那么你如何访问,我知道你可以触发一个动作来发送数据。
2021-05-30 13:09:03