Javascript 如何访问Redux reducer中的状态?

Javascript 如何访问Redux reducer中的状态?,javascript,reactjs,redux,Javascript,Reactjs,Redux,我有一个reducer,为了计算新的状态,我需要来自操作的数据,以及来自不由这个reducer管理的状态部分的数据。具体来说,在我将在下面展示的reducer中,我需要访问accountDetails.stateOfResidenceId字段 initialState.js: export default { accountDetails: { stateOfResidenceId: '', accountType: '', account

我有一个reducer,为了计算新的状态,我需要来自操作的数据,以及来自不由这个reducer管理的状态部分的数据。具体来说,在我将在下面展示的reducer中,我需要访问
accountDetails.stateOfResidenceId
字段

initialState.js:

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

        ]
    }
};
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;
  }
}
import { combineReducers } from 'redux';
import accountDetails from './accountDetailsReducer';
import forms from './formsReducer';

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

export default rootReducer;
formsReducer.js:

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

        ]
    }
};
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;
  }
}
import { combineReducers } from 'redux';
import accountDetails from './accountDetailsReducer';
import forms from './formsReducer';

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

export default rootReducer;
index.js(根减速器):

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

        ]
    }
};
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;
  }
}
import { combineReducers } from 'redux';
import accountDetails from './accountDetailsReducer';
import forms from './formsReducer';

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

export default rootReducer;

如何访问此字段?

在分派操作时,可以传递参数。在这种情况下,您可以将
accountDetails.stateOfResidenceId
传递给操作,然后将其作为有效负载传递给减速器。

您的选项是,除了使用
组合减速器之外,还可以编写更多逻辑,或者在操作中包含更多数据。Redux常见问题解答涵盖以下主题:


此外,我目前正在为Redux文档编写一组新的页面,主题是“结构化减缩器”,您可能会发现这很有帮助。当前WIP页面位于。

我建议您将其传递给动作创建者。 因此,在某个地方,您将有一个动作创建者,它可以执行以下操作:

updateProduct(arg1, arg2, stateOfResidenceId) {
  return {
    type: UPDATE_PRODUCT,
    stateOfResidenceId
  }
}
在触发动作的地方,假设您正在使用react,则可以使用

function mapStateToProps(state, ownProps) {
  return {
    stateOfResidenceId: state.accountdetails.stateOfResidenceId
  }  
}
并使用react redux的connect连接到react组件

connect(mapStateToProps)(YourReactComponent);
现在,在触发action updateProduct的react组件中,应该将stateOfResidenceId作为一个道具,并可以将其传递给action创建者

这听起来很复杂,但实际上是关于关注点的分离

我将使用以下示例:

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

    dispatch({
      type: UPDATE_PRODUCT,
      stateOfResidenceId: accountDetails.stateOfResidenceId,
      product,
    });
  };
}
基本上,您可以获得动作所需的所有数据,然后将这些数据发送到减速器。

您可以尝试使用:

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

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

但是,首先考虑是否最好将外部状态作为有效负载传递到操作中

我不确定这种方法是否是反模式的,但它对我有效。在动作中使用curried函数

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


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

如果您使用react-redux,并且只需要在一个位置执行该操作,或者您可以创建一个HOC(更高阶组件,不需要真正理解重要的是这可能会使html膨胀)需要访问的任何地方都要使用传递给操作的附加参数:

const-mapState=({accountDetails:{stateOfResidenceId}})=>stateOfResidenceId;
常量映射分派=(分派)=>({
pureUpdateProduct:(stateOfResidenceId)=>dispatch({type:types.UPDATE_PRODUCT,payload:stateOfResidenceId})
});
const mergeProps=(stateOfResidenceId,{pureUpdateProduct})=>({hydratedUpdateProduct:()=>pureUpdateProduct(stateOfResidenceId)});
const addHydratedUpdateProduct=connect(mapState、mapDispatch、mergeProps)
导出默认的AddHydreatedUpdateProduct(组件);
导出常量OtherHydreatedComponent=AddHydreatedUpdateProduct(OtherComponent)
当您使用mergeProps时,返回的内容将添加到props中,mapState和mapDispatch将仅用于提供mergeProps的参数。因此,换句话说,此函数会将其添加到组件props中(typescript语法):

(请注意,函数实际上返回操作本身,而不是void,但在大多数情况下,您将忽略这一点)

但你能做的是:

constmapstate=({accountDetails})=>accountDetails;
常量映射分派=(分派)=>({
pureUpdateProduct:(stateOfResidenceId)=>dispatch({type:types.UPDATE_PRODUCT,payload:stateOfResidenceId})
其他操作:(参数)=>调度(其他操作(参数))
});
const mergeProps=({stateOfResidenceId,…passAlong},{pureUpdateProduct,…otherActions})=>({
…很长时间,
……其他行动,
水合更新产品:()=>pureUpdateProduct(stateOfResidenceId),
});
const reduxPropsIncludingHydreatedAction=connect(映射状态、映射分派、合并Props)
导出默认ReduxPropsInIncludingHydreatedAction(ReactComponent);
这将为道具提供以下内容:

{
  hydratedUpdateProduct: () => void,
  otherAction: (param) => void,
  accountType: string,
  accountNumber: string,
  product: string,
}
总的来说,尽管redux维护人员对扩展其软件包的功能进行了彻底的解约,以一种良好的方式将这些愿望包括在内,这将在不支持生态系统碎片化的情况下为这些功能创建一种模式,但令人印象深刻


像Vuex这样不那么顽固的软件包不会因为人们滥用反模式而产生太多问题,因为它们会丢失,同时支持一种比你用redux和最好的支持软件包存档时更简洁的语法和更少的样板文件。尽管软件包更加通用,但documantation更容易撤销因为他们不会像Redux文档那样在细节中迷失方向。

如果您可以访问
存储
,那么您应该使用
store.getState()


这句话毫无意义。减速器功能的关键在于你根据当前状态和行动做出决策。感谢你的回答。我已经探索了你链接的一些资源,并将继续这样做。不过,我想问你一个问题,因为你似乎很有知识。另一个答案建议e使用
thunk
。你认为这是解决我问题的好办法吗?如果这会把我的代码弄得一团糟或者不是一个最佳做法,这不是我想要追求的解决办法,但我觉得我没有足够的知识来确定这些选择的长期影响。是的,thunk是管理副作用的标准基本方法s和执行复杂逻辑