Learn

The initialState structure has been defined and you know that the state of this application has 3 slices: allRecipes, favoriteRecipes, and searchTerm. Now, you can begin thinking about how the user will trigger changes to these slices of state through actions.

Remember, actions in Redux are represented by plain JavaScript objects that have a type property and are dispatched to the store using the store.dispatch() method.

When an application state has multiple slices, individual actions typically only change one slice at a time. Therefore, it is recommended that each action’s type follows the pattern 'sliceName/actionDescriptor', to clarify which slice of state should be updated.

For example, in a todo application with a state.todos slice, the action type for adding a new todo might be 'todos/addTodo'.

For the Recipes application, what do you think some of the action type strings might be? What user interactions might trigger them to be dispatched?

Write some of your ideas down before revealing the actions you will be using:

  1. 'allRecipes/loadData': This action will be dispatched to fetch the needed data from an API right when the application starts.

  2. 'favoriteRecipes/addRecipe': This action will be dispatched any time the user clicks on the ❤️ icon of a recipe from the full set of recipes.

  3. 'favoriteRecipes/removeRecipe': This action will be dispatched any time the user clicks on the 💔 icon of a recipe from their list of favorites.

  4. 'searchTerm/setSearchTerm': This action will be dispatched any time the user changes the text of the search input field to filter the full set of recipes.

  5. 'searchTerm/clearSearchTerm': This action will be dispatched any time the user clicks on the “X” button next to the search input field.


It’s also important to consider which of these actions will have a payload — additional data passed to the reducer in order to carry out the desired change-of-state. For example, consider the actions for the searchTerm slice:

store.dispatch({ type: 'searchTerm/setSearchTerm', payload: 'Spaghetti' }); // The resulting state: { ..., searchTerm: 'Spaghetti' } store.dispatch({ type: 'searchTerm/clearSearchTerm' }); // The resulting state: { ..., searchTerm: '' }
  • When the learner types in a search term, that data needs to be sent to the store so that the React components know which recipes to render and which to hide.
  • When the user clears the search field, no additional data needs to be sent because the store can simply set the search term to be an empty string again.

Once you have a clear idea of the types of actions that will be dispatched in your application, when they will be dispatched, and what payload data they will carry, the next step is to make action creators.

Remember, action creators are functions that return a formatted action object.

Action creators enable Redux programmers to re-use action object structures without typing them out by hand and they improve the readability of their code, particularly when dealing with bulky payloads.

Take a look at store.js where you will find that action creators for the two actions above have been defined for you. Your job is to create the remaining three: loadData(), addRecipe(), and removeRecipe()

Instructions

1.

Open up ./data.js and you will see an array of recipe objects called allRecipesData is exported. Back in store.js, at the top of the file, this array is imported (later on, you will fetch data from an API rather than importing from a local file).

This array needs to be sent to the store so that it can populate the state.allRecipes slice, which is initially empty. This can be done using the loadData() action creator.

Complete the function loadData() such that it returns an action object with the following properties:

  • type: The slice being modified is state.allRecipes and the action name is 'loadData'
  • payload: The allRecipesData array.

Remember to use the ‘sliceName/actionName’ pattern for type.

2.

Next up is addRecipe() which should be dispatched when the user clicks on the ❤️ icon of a particular recipe.

Notice that this function accepts a recipe parameter. The recipe object then needs to be sent to the store to be added to the state.favoriteRecipes slice. For example, this action might be dispatched like so:

const exampleRecipe = { id: 4, name: 'Cheeseburger', img: 'img/cheeseburger.jpg' } store.dispatch(addRecipe(exampleRecipe));

Complete the function called addRecipe() such that it returns an action object with the following properties:

  • type: The slice being modified is state.favoriteRecipes and the action name is 'addRecipe'
  • payload: The recipe object parameter.
3.

The last action creator is removeRecipe() which should be dispatched when the user clicks on the 💔 icon of a favorited recipe.

removeRecipe() also accepts a recipe parameter. The recipe object needs to be sent to the store so it knows which recipe to remove from the state.favoriteRecipes slice.

Complete the function called removeRecipe() such that it returns an action object with the following properties:

  • type: The slice being modified is state.favoriteRecipes and the action name is 'removeRecipe'
  • payload: The recipe object parameter.

Take this course for free

Mini Info Outline Icon
By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.

Or sign up using:

Already have an account?