I learn react with redux and can't understand how can I use state properties inside the reducers
I have created reducers file inside /reducers
folder
reducersText.js
export const textReducer = (state = [], action) => {
switch (action.type) {
case 'ADD_TEXT':
return state = action.payload;
default:
return state;
}
}
export const addCustomMinusWordReducer = (state = [], action) => {
switch (action.type) {
case 'ADD_CUSTOM_MINUS_WORD':
return state = action.payload;
default:
return state;
}
}
and I create index.js inside /reducers
folder
import {textReducer, addCustomMinusWordReducer} from "./text"
import {combineReducers} from "redux"
const allReducers = combineReducers({
text: textReducer,
customMinusWords: addCustomMinusWordReducer
})
export default allReducers
My problem is I can not access the text
state which created in textReducer
inside addCustomMinusWordReducer
.
I found related link, but this is not what I am looking for.
How can I use state in reducers?
Thanks!
From the official documentation of Redux:
Many users later want to try to share data between two reducers, but find that combineReducers does not allow them to do so. There are several approaches that can be used:
If a reducer needs to know data from another slice of state, the state tree shape may need to be reorganized so that a single reducer is handling more of the data.
You may need to write some custom functions for handling some of these actions. This may require replacing combineReducers with your own top-level reducer function. You can also use a utility such as reduce-reducers to run combineReducers to handle most actions, but also run a more specialized reducer for specific actions that cross state slices.
Async action creators such as redux-thunk have access to the entire state through getState(). An action creator can retrieve additional data from the state and put it in an action, so that each reducer has enough information to update its own state slice.
So, By exactly using your approach without using redux-thunk and without reordering the state with parent reducers. What you can do is pass in the state from action creators.
For example; One action creator would be:
const ExampleComponent = ({ text, clicked }) => {
return (
<button onClick={() => clicked(text)} />
);
};
export default connect(state => ({
text: state.text
}, dispatch => ({
clicked: (textState) => dispatch({ type: 'ADD_CUSTOM_MINUS_WORD', textState })
})(ExampleComponent);
And then in reducer you can simply do;
export const addCustomMinusWordReducer = (state = [], action) => {
// action.textState will contain the data from textState
// do something with action.textState
const { textState } = action;
}
If you would actually want to use global state inside reducers just as the documentation suggests easy way would be to use a utility such as reduce-reducers. Instead of using combineReducers
you could then use reduceReducers
. And in the reducer the state object will contain global state instead of local state that combineReducer would give.
PS:
As the previous answer suggested it is a bad idea to change state inside reducers which might cause hard to fix bugs in application.
so, Instead of state = state.payload
better idea would be to use spread operator like state = { ...state, ...state.payload }
which would then append changes to state rather than directly setting it.