可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a reducer, and in order to calculate the new state I need data from the action and also data from a part of the state not managed by this reducer. Specifically, in the reducer I will show below, I need access to the accountDetails.stateOfResidenceId
field.
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;
How can I access this field?
回答1:
I would use thunk for this, here's an example:
export function updateProduct(product) {
return (dispatch, getState) => {
const { accountDetails } = getState();
dispatch({
type: UPDATE_PRODUCT,
stateOfResidenceId: accountDetails.stateOfResidenceId,
product,
});
};
}
Basically you get all the data you need on the action, then you can send that data to your reducer.
回答2:
Your options are to either write more logic besides just use of combineReducers
, or include more data in the action. The Redux FAQ covers this topic: http://redux.js.org/docs/faq/Reducers.html#reducers-share-state .
Also, I'm currently working on a new set of pages to the Redux docs on the topic of "Structuring Reducers", which you may find helpful. The current WIP pages are at https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md .
回答3:
I sugguest that you pass it into the action creator.
So someplace you'll have an action creator that does something like this:
updateProduct(arg1, arg2, stateOfResidenceId) {
return {
type: UPDATE_PRODUCT,
stateOfResidenceId
}
}
At the place where you trigger the action, assume you are using react, you can use
function mapStateToProps(state, ownProps) {
return {
stateOfResidenceId: state.accountdetails.stateOfResidenceId
}
}
and connect to your react component using the react-redux's connect.
connect(mapStateToProps)(YourReactComponent);
Now, in your react component where you trigger the action updateProduct, you should have the stateOfResidenceId as a prop, and you can pass it to your action creator.
It sounds convoluted, but it is really about separation of concerns.
回答4:
You can try to use:
redux-named-reducers
Which allows you to get state anywhere in your code like so:
const localState1 = getState(reducerA.state1)
const localState2 = getState(reducerB.state2)
But think first if it would be better to pass the external state as a payload in the action.
回答5:
I'm not sure if this approach is an anti-pattern but it worked for me. Use a curried function in your actions.
export const myAction = (actionData) => (dispatch, getState) => {
dispatch({
type: 'SOME_ACTION_TYPE',
data: actionData,
state: getState()
});
}
回答6:
While dispatching an action, you can pass a parameter. In this case, you could pass accountDetails.stateOfResidenceId
to the action and then pass it on to the reducer as payload.