I'm trying to trigger a simple action using @reduxjs/Toolkit but it's not working.
I see that the action is dispatched but it's like the slice reducer is not listening to it or something.
const say = createAction("ui/say", what => ({ payload: what }));
const uiSlice = createSlice({
name: "ui",
initialState: { said: "" },
reducers: {
[say.type]: (state, action) => {
console.log("saying", action.payload); //<-- not showing, why?
state.currentList = action.payload;
}
}
});
const store = configureStore({
reducer: combineReducers({
ui: uiSlice.reducer
})
});
const Chat = () => {
const dispatch = useDispatch();
const [whatToSay, setWhatToSay] = useState("");
const whatWasSaid = useSelector(state => state.ui.said);
const onSubmit = e => {
e.preventDefault();
dispatch(say(whatToSay));
setWhatToSay("");
};
return (
<div>
<form onSubmit={onSubmit}>
<input type="text" onChange={e => setWhatToSay(e.target.value)} />
<button>Say</button>
</form>
{whatWasSaid ? <p>You said: {whatWasSaid}</p> : <p>Say something</p>}
</div>
);
};
Here's a minimal reproducing example: https://codesandbox.io/s/redux-toolkit-0tzxs?file=/src/index.js
Create a Redux State SliceAdd a new file named src/features/counter/counterSlice.js . In that file, import the createSlice API from Redux Toolkit. Creating a slice requires a string name to identify the slice, an initial state value, and one or more reducer functions to define how the state can be updated.
Dispatching an action within a reducer is an anti-pattern. Your reducer should be without side effects, simply digesting the action payload and returning a new state object. Adding listeners and dispatching actions within the reducer can lead to chained actions and other side effects.
Redux Toolkit's RTK Query data fetching API is a purpose built data fetching and caching solution for Redux apps, and can eliminate the need to write any thunks or reducers to manage data fetching.
I think you mismatched the createSlice
API.
From your code, you trying to implement a listener for an action, so you might want to use extraReducers
instead:
const uiSlice = createSlice({
name: "ui",
initialState: { said: "" },
// Not reducers: {}
extraReducers: {
[say.type]: (state, action) => {
console.log("saying", action.payload);
state.currentList = action.payload;
}
}
});
Note the reducers
prop of createSlice
API:
reducers: Object<string, ReducerFunction | ReducerAndPrepareObject>
If you want to use say
in reducers
it should be:
const say = (state, payload) => {
console.log("saying", payload);
state.currentList = payload;
};
const uiSlice = createSlice({
name: "ui",
initialState: { said: "" },
reducers: { say }
});
// Usage
dispatch(uiSlice.actions.say(whatToSay));
@markerikson: with
createSlice
, the reducers field is for defining reducers and generating actions that will match those reducers. TheextraReducers
field is for handling actions that were already defined elsewhere.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With