FAQ: Strategies for Complex State - Actions and Payloads For Complex State

This community-built FAQ covers the “Actions and Payloads For Complex State” exercise from the lesson “Strategies for Complex State”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Learn Redux

FAQs on the exercise Actions and Payloads For Complex State

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!
You can also find further discussion and get answers to your questions over in Language Help.

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head to Language Help and Tips and Resources. If you are wanting feedback or inspiration for a project, check out Projects.

Looking for motivation to keep learning? Join our wider discussions in Community

Learn more about how to use this guide.

Found a bug? Report it online, or post in Bug Reporting

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

// Dispatched when the user clicks on the heart icon of 
// a recipe in the "All Recipes" section.
// Sends the recipe object to the store.

const addRecipe = (recipe) => {
  return {
    type: "favoriteRecipes/addRecipe",
    payload: recipe
  }
}

So what is the parameter, recipe for?

Hi!
I’m getting the following error when running the code in this exercise:

“Oops! The test returned an error. Maybe you have a syntax error, or a typo”
Browserslist: caniuse-lite is outdated. Please run:
npx browserslist@latest --update-db

I’ve tried reloading the page, reopening the browser, but nothing seems to work.
It doesn’t seem to be an error with my code (which is quite simple for this exercise anyway).
This prevents me from progressing in this course, so any help would be appreciated.

additional info in the error pane:

{
  "stats": {
    "suites": 0,
    "tests": 1,
    "passes": 1,
    "pending": 0,
    "failures": 0,
    "start": "2021-07-25T09:06:29.067Z",
    "end": "2021-07-25T09:06:29.127Z",
    "duration": 60
  },
  "tests": [
    {
      "title": "",
      "fullTitle": " ",
      "duration": 56,
      "currentRetry": 0,
      "err": {}
    }
  ],
  "pending": [],
  "failures": [],
  "passes": [
    {
      "title": "",
      "fullTitle": " ",
      "duration": 56,
      "currentRetry": 0,
      "err": {}
    }
  ]
}
1 Like

I don’t see why just using loadData instead of allRecipes/loadData won’t work, in the action object.

Is the loadData() action creator for the specific use case of using useEffect() part of the Redux pattern?
I am asking this because setting the initialState of AllRecipes to allRecipesData instead to [], the same result is achieved with less complex code. Besides that, can the rendering of the recipes be considered a side effect in order to justify the use of useEffect()?

// if setting initialState of allRecipes to allRecipesData like so:

// the loadData action creator is no longer needed
export const loadData = () => {
  return {
    type: 'allRecipes/loadData',
    payload: allRecipesData
  }
}


const initialState = allRecipesData;  // initialState is initialized with allRecipesData
export const allRecipesReducer = (allRecipes = initialState, action) => {
  switch (action.type) {
    case 'allRecipes/loadData': //this action is no longer needed.
      return action.payload;
    case 'favoriteRecipes/addRecipe': 
      return allRecipes.filter(recipe => recipe.id !== action.payload.id);
    case 'favoriteRecipes/removeRecipe':
       return [...allRecipes, action.payload]
    default:
      return allRecipes;
  }
}
// then, this code is not needed if the render of the recipes on first load is not a side effect. allRecipes will render for the first time with all the data needed to render the recipes
const onFirstRender = () => { /
 dispatch(loadData()); 
   }
 useEffect(onFirstRender, [dispatch])

On a second question/comment, the code used to render the recipes is slightly different from allRecipes to favoriteRecipes, althought the outcome is equivalent. I think this is just an inconsistency issue: two ways of doing the same thing. But it has confused me for a while. I consider that helper function in favoriteRecipes a bit verbose. But maybe is the other way around and I should start to get used to this pattern. In any case, I think both should be the same.

// allRecipes.js

return (
    <div className="recipes-container">
      {allRecipes.map((recipe) => (
        <Recipe recipe={recipe} key={recipe.id}>
          <FavoriteButton
            onClickHandler={() => onAddRecipeHandler(recipe)}
            icon={favoriteIconURL}
          >
            Add to Favorites
          </FavoriteButton>
        </Recipe>
      ))}
    </div>
  );

vs


// favoriteRecipes.js
return (
    <div className="recipes-container">
      {favoriteRecipes.map(createRecipeComponent)}
    </div>
  );

  // Helper Function
  function createRecipeComponent(recipe) {
    return (
      <Recipe recipe={recipe} key={recipe.id}>
        <FavoriteButton
          onClickHandler={() => onRemoveRecipeHandler(recipe)}
          icon={unfavoriteIconUrl}
        >
          Remove Favorite
        </FavoriteButton>
      </Recipe>
    )
  } 

I just have a general question about actions in Redux: Why do they have to be functions? It seems to me that functionally:

const foo = () => {
  return {
    action: bar
  }
}

is functionally the same as

const foo = {action: bar}

Another general question. Why do the switch statements in Redux reducers not have break; after each case statement? I remember learning that this was necessary both on the C and the JavaScript courses, so was surprised to see it absent.

I haven’t done this course so I can only comment in a general fashion, but the first is a function whereas the latter is a single object.

If the function had a parameter i.e.

const foo = (bar) => { ...

then the function can be reused to create multiple objects.

For Example, consider

Using a function to create similar objects but with different values,

Click to see Function Example
const person = (name, age, hobbies) => {
  return {
    name: name,
    age: age,
    hobbies: hobbies
  }
}

const person1 = person("Jack", 10, ["writing", "playing"])
const person2 = person("Jill", 13, ["riding", "soccer"])
const person3 = person("Frank", 16, ["chess", "math club", "cooking"])

as opposed to having to declare and initialize separate objects leading to duplication of code,

Click to see single objects
const person1 = {
    name: "Jack",
    age: 10,
    hobbies: ["writing", "playing"]
}

const person2 = {
    name: "Jill",
    age: 13,
    hobbies: ["riding", "soccer"]
}

const person3 = {
    name: "Frank",
    age: 16,
    hobbies: ["chess", "math club", "cooking"]
}

The function allows you to create as many objects as you want just by passing different arguments to the function. In contrast, the latter approach would require you to manually duplicate similar objects whose keys and structure is same but only the values are different. The more objects that need to be created, the more the unnecessary duplication of code in the latter approach.

If that isn’t what you were asking, then I need more elaboration and context to understand your line of thought.

You haven’t shared a snippet of code illustrating your observation. I am assuming that the cases are using the return keyword. If so, then there is no danger of fall-through, because the return will immediately cause you to exit.

For Example,

Here, break is necessary. Without break statements, we fall through.

Example where break is necessary
function f(num) {
    
    switch (num) {
        case 1:
            console.log("One");
        case 2:
            console.log("Two");
        case 3:
            console.log("Three");
        default:
            console.log("Not in range 1-3");
    }
}
    
f(2);

// Output:
"Two"
"Three"
"Not in range 1-3"

Here break is not necessary, because we return immediately,

Example where break is not necessary
function f(num) {
    
    switch (num) {
        case 1:
            return "One";
        case 2:
            return "Two";
        case 3:
            return "Three";
        default:
            return "Not in range 1-3";
    }
}
    
console.log(f(2));

// Output:
"Two"
1 Like

Hello, thank you both of your answers are helpful, I think you’re probably right that the possiblitiy to pass a parameter in is why Redux requires actions to be functions (or why we are taught to package actions as functions, even ones that do not have any modifiable parts). You’re right that the switch statements in Redux all have a return statement, so that explains why break is not needed in each case, thank you!

2 Likes