In the last exercise, we looked at one way to define a slice reducer and the associated action creators.
/* todosSlice.js */ const addTodo = (todo) => { // logic omitted... } const toggleTodo = (todo) => { // logic omitted... } const todos = (state = [], action) => { // logic omitted... }
We can do the same work, but more simply, with createSlice()
! createSlice()
has one parameter, options
, which is an object with the following properties
name
: a string that is used as the prefix for generated action typesinitialState
: the initial state value for the reducerreducers
: an object of methods, where the keys determine the actiontype
strings that can update the state, and whose methods are reducers that will be executed when that action type is dispatched. These are sometimes referred to as “case reducers”, because they’re similar to a case in a switch statement.
/* todosSlice.js */ const options = { name: 'todos', initialState: [], reducers: { addTodo: (state, action) => { return [ ...state, { id: action.payload.id, text: action.payload.text, completed: false } ] }, toggleTodo: (state, action) => { return state.map(todo => (todo.id === action.payload.id) ? { ...todo, completed: !todo.completed } : todo ) } } } const todosSlice = createSlice(options);
In the options
object passed to createSlice()
in the snippet above, name
is set to 'todos'
, initialState
is set to an empty array, and we have two case reducers: addTodo
and toggleTodo
. Note that the names of the case reducer functions are conventionally written in lowerCamelCase.
With createSlice()
…
- We can write the case reducers as functions inside of an object, instead of having to write a switch/case statement.
- Action creators that correspond to each case reducer function we provide will be automatically generated, so we don’t need to worry about defining those ourselves.
- No default handler needs to be written. The reducer generated by
createSlice()
will automatically handle all other action types by returning the current state, so we don’t have to list that ourselves.
For now, let’s practice calling createSlice()
. In the next exercise, we’ll take a look at the object that is returned by createSlice()
.
Instructions
Take a look at oldFavoriteRecipesSlice.js to see the old way of creating a reducer and action creators for the state.favoriteRecipes
slice. Your job is to rewrite this code using createSlice
within favoriteRecipesSlice.js.
First, createSlice()
will need an options
object to be passed in as an argument. At the top of the file and below the import
statements, declare a variable called options
. For now, assign to it an empty object.
Next, add the following three properties and corresponding values to the options
object:
name
:'favoriteRecipes'
initialState
: an empty arrayreducers
: an empty object (for now).
The options.reducers
property should hold an object containing the case reducers for the slice.
- Each value in the
options.reducers
object should be a function whose name corresponds to an action type that the slice can handle. - Each case reducer should have two parameters,
state
andaction
, and return the next state.
Using the logic defined in the oldFavoriteRecipesSlice.js file to guide you, add the two methods below to the options.reducers
object:
addRecipe
removeRecipe
Well done! The final step is to call createSlice()
with the options
object as an argument and export the result.
Below the options
object,
- Declare a new variable called
favoriteRecipesSlice
- Call
createSlice()
withoptions
as the only argument and assign the result tofavoriteRecipesSlice
- Export
favoriteRecipesSlice