如何访问Redux减速机内部的状态?

时间:2016-08-31 19:40:49

标签: javascript reactjs redux

我有一个reducer,为了计算新状态,我需要动作中的数据以及来自该reducer未管理的部分状态的数据。具体来说,在我将在下面显示的reducer中,我需要访问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(root reducer):

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

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

export default rootReducer;

如何访问此字段?

9 个答案:

答案 0 :(得分:75)

我会使用thunk来做这个,这是一个例子:

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

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

基本上,您可以获得操作所需的所有数据,然后您可以将该数据发送到减速器。

答案 1 :(得分:8)

除了使用combineReducers之外,您可以选择编写更多逻辑,或者在操作中包含更多数据。 Redux常见问题涵盖了此主题:http://redux.js.org/docs/faq/Reducers.html#reducers-share-state

另外,我目前正在为Redux文档开发一个关于“Structuring Reducers”主题的新页面,您可能会觉得这些页面很有帮助。当前的WIP页面位于https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md

答案 2 :(得分:0)

我建议你把它传递给动作创作者。 所以在某个地方你会有一个行动创造者做这样的事情:

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

在您触发操作的地方,假设您正在使用反应,您可以使用

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

并使用react-redux的connect连接到您的react组件。

connect(mapStateToProps)(YourReactComponent);

现在,在您触发动作updateProduct的react组件中,您应该将stateOfResidenceId作为prop,并且可以将其传递给您的action creator。

这听起来很复杂,但它确实是关注点的分离。

答案 3 :(得分:0)

您可以尝试使用:

redux-named-reducers

允许您在代码中的任何位置获取状态,如下所示:

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

但首先考虑一下将外部状态作为有效负载传递给动作会更好。

答案 4 :(得分:0)

我不确定这种方法是否是反模式,但它是否对我有用。在操作中使用咖喱函数。

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

答案 5 :(得分:0)

编写符合您想要的功能的组合函数很简单:

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。

这种方法的好处是,您只公开所需的状态片,而不是整个状态。

答案 6 :(得分:0)

另一种方法,如果您使用react-redux并且只需要在一个地方执行该操作,或者创建HOC很好(更高的oder组件,则实际上不需要了解重要的内容可能会使您的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}

(请注意,该函数实际上会返回操作本身,而不是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表示完全不赞成,但他们很好地扩展了其软件包的功能以包含这些愿望,这将为这些功能创建模式,而无需支持生态系统的碎片化, / p>

像Vuex这样不那么顽固的软件包在人们滥用反模式方面会遇到很多问题,因为它们丢失了,同时还支持一种更简洁的语法,比您使用redux和最好的支持软件包进行归档要少。而且,尽管该软件包具有更多用途,但易于理解,因为它们不会像reduxs文档那样在细节中迷失方向。

答案 7 :(得分:0)

如果您有权访问 store,那么您应该使用 store.getState()

https://redux.js.org/api/store#getstate

答案 8 :(得分:-2)

在调度操作时,您可以传递参数。在这种情况下,您可以将accountDetails.stateOfResidenceId传递给操作,然后将其作为有效负载传递给reducer。