web-dev-qa-db-ja.com

別の減速機内のある減速機から減速機状態の一部にアクセスする

_reducerForm.js_の_reducerRegister.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

    };
}
_
16
Ilija Bradaš

これは、Redux FAQ at http://redux.js.org/docs/faq/Reducers.html#reducers-share-state

多くのユーザーは、後で2つのレデューサー間でデータを共有しようとしますが、combinedReducersではそれらを許可しないことに気付きます。使用できるアプローチはいくつかあります。

  • レデューサーが別の状態のスライスからのデータを知る必要がある場合、単一のレデューサーがより多くのデータを処理するように、状態ツリーの形状を再編成する必要がある場合があります。
  • これらのアクションの一部を処理するために、いくつかのカスタム関数を作成する必要がある場合があります。これには、combineReducersを独自の最上位レデューサー関数に置き換える必要がある場合があります。また、reduce-reducersなどのユーティリティを使用して、combineReducersを実行してほとんどのアクションを処理できますが、状態スライスを横断する特定のアクションに対して、より特化したリデューサーを実行することもできます。
  • Redux-thunkなどの非同期アクション作成者は、getState()を介して状態全体にアクセスできます。アクション作成者は、状態から追加のデータを取得してアクションに入れることができます。これにより、各レデューサーは自身の状態スライスを更新するのに十分な情報を取得できます。
21
markerikson

レデューサーは別のレデューサーの状態にアクセスできませんが、 redux-thunk を使用している場合は、アクション作成者からアクセスできます。例として、次のようなアクションクリエーターを定義できます。

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

React Reduxは単方向のデータフローで動作します。

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

Reducerは、ストアの小さなサブセットで動作します。Reducerの一部ではないreducer内のストアにはアクセスできません。リデューサーの状態の戻り値に基づいて、コンポーネントから新しいアクションを起動する必要があります。

6
Khalid Azam