Our slice to handle our fruits state will be:
import {createSlice} from '@reduxjs/toolkit';
const initialState = {fruits: []};
const fruitsSlice = createSlice({
name: 'fruits',
initialState,
reducers:{
addFruit(state, action){
console.log(action);
state.fruits = [...state.fruits, action.payload];
}
}
});
export const {addFruit} = fruitsSlice.actions;
export default fruitsSlice;
We can dispatch an action to update the addFruits reducer by calling it with the same name action.
const addFruitHandler = ()=>{
setError(null);
if(fruitName.length > 0 && Number.isInteger(fruitCount) && fruitCount > 0){
console.log(fruitName, fruitCount);
dispatch(addFruit({fruitName, fruitCount})); //dispatching action
}
......
}
Lets breakdown what happening,
- Our fruits slice is created from
createSlice
function provided by the RTK library. -
createSlice
accepts an object with three mandatory properties: name, initialState, reducers.-
name
is used when dispatching an action.(more on this later). -
initialState
is the initial state that this reducer will have.In our example, I have given an initial state.
const initialState = {fruits: []}
Note: Use
null
if we want to set initialState as empty.-
reducers
is an object containing Redux "case reducer" functions.It will have one or more actions depending on our application requirement.Here,I am creating one actionaddFruit
to add a fruit object to our existing fruit list.
-
Finally, we are exporting the actions of this slice and the fruitSlice.
We will now link the reducer from fruitsSlice in our store.
We can architect our code better by extracting out the actions in its own file.
Create a folder actions
in our src folder and add a new file fruits.js
inside it.
Let us take a deep look at the name
of the slice and dispatch code inside AddFruit.js
dispatch(addFruit({fruitName, fruitCount}));
Here, we are dispatching an object with fruitName and fruitCount.
By default, the action object of addFruit
reducer will be
{type: "fruits/addFruit", payload: {fruitName: 'peach', fruitCount: 1}
.
Type is formed by <slice name>/<action name>
and payload is the parameter we pass in the dispatch function.
There is a bit of issue in the way we are dispatching our fruit name and count.
We have to make sure other components also dispatch with same object structure({fruitName:'',fruitCount:''}) which is a bad practice.
For that we create a custom payload by modifying our slice action,
const fruitsSlice = createSlice({
....
reducers:{
addFruit:{
reducer: (state, action)=>{
state.fruitList = [...state.fruitList, action.payload];
},
prepare: (name, count)=>{
return {payload: {name, count}};
}
}
}
});
and our dispatch will now simply be
dispatch(addFruit(fruitName, fruitCount));
The prepare method can accept any paramaters and returns a custom payload.
Now, we will be consuming the fruit list from our fruits state in FruitList component.
That's it!
The final application can be found here:
https://github.com/abhidatta0/fruits-logger-redux-toolkit
Top comments (0)