[javascript] Redux 감속기 내부의 상태에 액세스하는 방법은 무엇입니까?

나는 감속기가 있고 새로운 상태를 계산하기 위해서는 액션의 데이터 와이 감속기가 관리하지 않는 상태의 일부의 데이터가 필요합니다. 특히 아래에 표시 할 감속기에서 accountDetails.stateOfResidenceId필드에 대한 액세스 권한이 필요 합니다.

initialState.js :

export default {
    accountDetails: {
        stateOfResidenceId: '',
        accountType: '',
        accountNumber: '',
        product: ''
    },
    forms: {
        blueprints: [

        ]
    }
};

formsReducer.js :

import * as types from '../constants/actionTypes';
import objectAssign from 'object-assign';
import initialState from './initialState';
import formsHelper from '../utils/FormsHelper';
export default function formsReducer(state = initialState.forms, action) {
  switch (action.type) {
    case types.UPDATE_PRODUCT: {
        //I NEED accountDetails.stateOfResidenceId HERE
        console.log(state);
        const formBlueprints = formsHelper.getFormsByProductId(action.product.id);
        return objectAssign({}, state, {blueprints: formBlueprints});
    }

    default:
      return state;
  }
}

index.js (루트 감속기) :

import { combineReducers } from 'redux';
import accountDetails from './accountDetailsReducer';
import forms from './formsReducer';

const rootReducer = combineReducers({
    accountDetails,
    forms
});

export default rootReducer;

이 필드에 어떻게 액세스 할 수 있습니까?



답변

이를 위해 썽크 를 사용할 것입니다 . 여기에 예가 있습니다.

export function updateProduct(product) {
  return (dispatch, getState) => {
    const { accountDetails } = getState();

    dispatch({
      type: UPDATE_PRODUCT,
      stateOfResidenceId: accountDetails.stateOfResidenceId,
      product,
    });
  };
}

기본적으로 작업에 필요한 모든 데이터를 얻은 다음 해당 데이터를 감속기로 보낼 수 있습니다.


답변

옵션은를 사용하는 것 외에 더 많은 논리를 작성 combineReducers하거나 작업에 더 많은 데이터를 포함하는 것입니다. Redux FAQ는이 주제를 다룹니다.

https://redux.js.org/faq/reducers/

또한 저는 현재 “Structuring Reducers”주제에 대한 Redux 문서의 새로운 페이지 세트를 작업 중이며 도움이 될 것입니다. 현재 WIP 페이지는 https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md에 있습니다.


답변

이 접근 방식이 안티 패턴인지 확실하지 않지만 저에게 효과적이었습니다. 당신의 행동에 카레 기능을 사용하십시오.

export const myAction = (actionData) => (dispatch, getState) => {
   dispatch({
      type: 'SOME_ACTION_TYPE',
      data: actionData,
      state: getState()
   });
}


답변

원하는 것을 정확히 수행하는 결합 함수를 작성하는 것은 간단합니다.

import accountDetails from './accountDetailsReducer';
import forms from './formsReducer';

const rootReducer = (state, action) => {
        const newState = {};

        newState.accountDetails = accountDetails(state.accountDetails, action);
        newState.forms = forms(state.forms, action, state.accountDetails);

        return newState;
    };

export default rootReducer;

FormReducer는 다음과 같습니다.

export default function formsReducer(state = initialState.forms, action, accountDetails) {

이제 formsReducer가 accountDetails에 액세스 할 수 있습니다.

이 접근 방식의 이점은 전체 상태가 아니라 필요한 상태 조각 만 노출한다는 것입니다.


답변

나는 당신이 그것을 액션 창조자에게 전달하는 것을 권합니다. 따라서 어딘가에 다음과 같은 작업을 수행하는 액션 제작자가 있습니다.

updateProduct(arg1, arg2, stateOfResidenceId) {
  return {
    type: UPDATE_PRODUCT,
    stateOfResidenceId
  }
}

액션을 트리거하는 곳에서 react를 사용한다고 가정하면

function mapStateToProps(state, ownProps) {
  return {
    stateOfResidenceId: state.accountdetails.stateOfResidenceId
  }
}

react-redux의 연결을 사용하여 반응 구성 요소에 연결하십시오.

connect(mapStateToProps)(YourReactComponent);

이제 updateProduct 작업을 트리거하는 반응 구성 요소에서 stateOfResidenceId를 소품으로 가져야하며이를 작업 작성자에게 전달할 수 있습니다.

복잡하게 들리지만 실제로는 우려의 분리에 관한 것입니다.


답변

다음을 사용해 볼 수 있습니다.

redux-named-reducers

다음과 같이 코드의 어느 곳에서나 상태를 얻을 수 있습니다.

const localState1 = getState(reducerA.state1)
const localState2 = getState(reducerB.state2)

그러나 액션의 페이로드로 외부 상태를 전달하는 것이 더 나은지 먼저 생각하십시오.


답변

다른 방법으로 react-redux를 사용하고 한 곳에서만 해당 작업이 필요하거나 HOC (Higher oder component)를 생성해도 괜찮은 경우 필요한 모든 곳에서 중요한 점은 이것이 html을 부 풀릴 수 있다는 사실을 이해할 필요가 없습니다. 해당 액세스는 조치에 전달되는 추가 매개 변수와 함께 mergeprops 를 사용 하는 것입니다.

const mapState = ({accountDetails: {stateOfResidenceId}}) => stateOfResidenceId;

const mapDispatch = (dispatch) => ({
  pureUpdateProduct: (stateOfResidenceId) => dispatch({ type: types.UPDATE_PRODUCT, payload: stateOfResidenceId })
});

const mergeProps = (stateOfResidenceId, { pureUpdateProduct}) => ({hydratedUpdateProduct: () => pureUpdateProduct(stateOfResidenceId )});

const addHydratedUpdateProduct = connect(mapState, mapDispatch, mergeProps)

export default addHydratedUpdateProduct(ReactComponent);

export const OtherHydratedComponent = addHydratedUpdateProduct(OtherComponent)

mergeProps를 사용하면 반환 된 내용이 props에 추가되고 mapState 및 mapDispatch는 mergeProps에 대한 인수를 제공하는 역할 만합니다. 즉,이 함수는이를 컴포넌트 소품 (타입 스크립트 구문)에 추가합니다.

{hydratedUpdateProduct: () => void}

(함수는 실제로 무효가 아닌 액션 자체를 반환하지만 대부분의 경우 무시합니다).

하지만 할 수있는 일은 다음과 같습니다.

const mapState = ({ accountDetails }) => accountDetails;

const mapDispatch = (dispatch) => ({
  pureUpdateProduct: (stateOfResidenceId) => dispatch({ type: types.UPDATE_PRODUCT, payload: stateOfResidenceId })
  otherAction: (param) => dispatch(otherAction(param))
});

const mergeProps = ({ stateOfResidenceId, ...passAlong }, { pureUpdateProduct, ... otherActions}) => ({
  ...passAlong,
  ...otherActions,
  hydratedUpdateProduct: () => pureUpdateProduct(stateOfResidenceId ),
});

const reduxPropsIncludingHydratedAction= connect(mapState, mapDispatch, mergeProps)

export default reduxPropsIncludingHydratedAction(ReactComponent);

이것은 소품에 다음과 같은 것들을 제공 할 것입니다 :

{
  hydratedUpdateProduct: () => void,
  otherAction: (param) => void,
  accountType: string,
  accountNumber: string,
  product: string,
}

전반적으로 redux-maintainers가 패키지의 기능을 확장하여 그러한 소원을 좋은 방식으로 포함하도록 보여 주었지만 생태계의 단편화를 지원하지 않고 이러한 기능에 대한 패턴을 생성하는 것은 인상적입니다.

그렇게 고집스럽지 않은 Vuex와 같은 패키지는 안티 패턴을 남용하는 사람들에게 거의 많은 문제가 없습니다. 그리고 패키지가 훨씬 더 다재다능 함에도 불구하고 redux 문서와 같은 세부 사항에서 길을 잃지 않기 때문에 문서화가 이해하기 쉽습니다.