我有一个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;
如何访问此字段?
答案 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)
您可以尝试使用:
允许您在代码中的任何位置获取状态,如下所示:
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()
。
答案 8 :(得分:-2)
在调度操作时,您可以传递参数。在这种情况下,您可以将accountDetails.stateOfResidenceId
传递给操作,然后将其作为有效负载传递给reducer。