the title may be misleading but here is what happened:
reducer.js:
// initial state
const initialState = {
notes: [
{
content: "reducer defines how redux store works",
important: true,
id: 1,
},
{
content: "state of store can contain any data",
important: false,
id: 2,
},
],
filter: "IMPORTANT",
};
// reducer
const noteReducer = (state = initialState, action) => {
switch (action.type) {
case "NEW_NOTE":
console.log("state", state);
return state.notes.concat(action.data);
// ...
}
const generateId = () => Math.floor(Math.random() * 1000000);
// action
export const createNote = (content) => {
return {
type: "NEW_NOTE",
data: {
content,
important: false,
id: generateId(),
},
};
};
in index.js:
const reducer = combineReducers({
notes: noteReducer,
filter: filterReducer,
});
const store = createStore(reducer, composeWithDevTools());
//dispatch a note from index.js
//it works here
store.dispatch(
createNote("combineReducers forms one reducer from many simple reducers")
);
returns in the console.log("state", state);
in reducer.js:
state
{notes: Array(2), filter: 'IMPORTANT'}
filter: "IMPORTANT" // 'filter' is here
notes: (2) [{…}, {…}]
[[Prototype]]: Object //prototype is object
Here createNote
is successful.
However, when creating a new note through:
const NewNote = (props) => {
const dispatch = useDispatch();
const addNote = (event) => {
event.preventDefault();
const content = event.target.note.value;
event.target.note.value = "";
// createNote does not work here
dispatch(createNote(content));
};
return (
<form onSubmit={addNote}>
<input name="note" />
<button type="submit">add</button>
</form>
);
};
Here the console.log("state", state);
returns:
state
(3) [{…}, {…}, {…}]
0: {content: 'reducer defines how redux store works', important: true, id: 1}
1: {content: 'state of store can contain any data', important: false, id: 2}
2: {content: 'combineReducers forms one reducer from many simple reducers', important: false, id: 824517}
length: 3
// 'filter' is missing
[[Prototype]]: Array(0) // state prototype changed to array
In which the filter
is gone from the state, so the creation is not successful.
In short, store.dispatch( createNote("...") );
works but not dispatch(createNote(content));
.
The reason seems to be that noteReducer
received different states. But in both cases filter
is not specified.
I wonder why this happens and how to solve it?
CodePudding user response:
as we know when you are using a reducer the reducer takes 2 parameters one for initial stat and the other for action.
any action will be run in the reducer you need to save the old state
by used spread operator {...state}
case "NEW_NOTE": console.log("state", state); {...state, notes: state.notes.concat(action.data)}
CodePudding user response:
found the issue.
noteReducer should be:
const noteReducer = (state = initialState, action) => {
switch (action.type) {
case "NEW_NOTE":
return { ...state, notes: state.notes.concat(action.data) };
//...
}
just found out that above is a wrong fix. the right one is actually is:
const noteReducer = (state = initialState.notes, action) => {
otherwise noteReducer
is changing the filter as well. but it should be changing the 'note'
part only.