I wanted to understand the use of the name parameter in the createSlice function of the Redux-Toolkit API.
import { createSlice } from "@reduxjs/toolkit";
const cartSlice = createSlice({
name: "cartSlice", // Used for internal purposes
initialState: {
item: [],
cost: 0,
},
reducers: {
addItem: (state, action) => {
state.item.push(action.payload);
++state.cost;
},
removeItem: (state) => {
state.item.pop();
--state.cost;
},
clearCart: (state) => {
state.item.length = 0;
// state.item.length = [] won't work for some reason
state.cost = 0;
},
},
});
export const { addItem, removeItem, clearCart } = cartSlice.actions;
export default cartSlice.reducer;
From their documentation, name parameter:
A string name for this slice of state. Generated action type constants will use this as a prefix.
Unfortunately, I did not get a clear picture of what's happening even after reading this line. My main confusion stems from the fact that while creating a Store in Redux Toolkit, we do something like this -
import { configureStore } from "@reduxjs/toolkit";
import cartSlice from "./cartSlice";
export default appStore = configureStore({
reducer: {
cart: cartSlice,
},
});
In configureStore function, we are passing an object. From the documentation -
If it is an object of slice reducers, like
{ users: usersReducer, posts: postsReducer }
, configureStore will automatically create the root reducer by passing this object to the Redux combineReducers utility.
Now when using react-redux
in my App (React), I am able to access this particular Slice State via what I defined in the configureStore function, which is cart here and not cartSlice.
I find this extremely confusing.
What is the actual use of the name paramter in the createSlice
function then, if not to give the State slice a name for reference in our main code? Is it just used for internal purposes?
I tried to read the documentation but could not understand what's happeneing.
From their documentation, name parameter:
A string name for this slice of state. Generated action type constants will use this as a prefix.
Unfortunately, I did not get a clear picture of what's happening even after reading this line.
It really is much simpler than you are thinking it is. The slice name is only used to name scope the generated actions.
Given slice:
const cartSlice = createSlice({
name: "cartSlice",
initialState: {
item: [],
cost: 0,
},
reducers: {
addItem: (state, action) => {
state.item.push(action.payload);
++state.cost;
},
removeItem: (state) => {
state.item.pop();
--state.cost;
},
clearCart: (state) => {
state.item = []; // <-- just "reset" back to empty array
state.cost = 0;
},
},
});
The generated addItem
, removeItem
, and clearCart
actions will have action types "cartSlice/addItem"
, "cartSlice/removeItem"`` and
"cartSlice/clearCart"` respectively. If you enable the Redux-Devtools and install the browser extension, you can actually see these as the dispatched actions to the store along with their payloads and the incremental state updates in the store.
The name used to identify a reducer function when using the configureStore
or combineReducers
functions is completely separate and independent of the individual state slice's name
property. How you merge the reducers is how you create the state tree, e.g state.cart.item
, when selecting from state in the UI components, e.g. const cartItems = useSelector(state => state.cart.item);
.