FAQ: The Effect Hook - Separate Hooks for Separate Effects

This community-built FAQ covers the “Separate Hooks for Separate Effects” exercise from the lesson “The Effect Hook”.

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

Learn React

FAQs on the exercise Separate Hooks for Separate Effects

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!

Note:
I have reported a bug. My code below was “passed” as valid from the existing “tests” installed in the dependency files. My code below is WRONG. The app did not work even though my code passed all the tests. So, I did find the errors by comparing my code to the solution and suggest if your app is not working you might compare your answer side by side to the solution to discover the simple fix. You can see in my code below the incorrect syntax was used for the setters.

setMenu(menuResponse.data);
setNewsFeed(newsFeedResponse.data);
setFriends(friendsResponse.data);

should have been

setMenu(response.data);
setNewsFeed(response.data);
setFriends(response.data);
//mine is different than the given solution but the Codecademy solution checker doesn't catch the mistakes. 
//you must compare to the solution to see your mistakes from this point.  
import React, { useState, useEffect } from 'react';
import { get } from './mockBackend/fetch';

export default function SocialNetwork() {
  const [menu, setMenu] = useState(null);
    useEffect(() => {
      get('/menu').then((response) => {
        setMenu(menuResponse.data);
      });
   }, []);

  const [newsFeed, setNewsFeed] = useState(null);
  useEffect(() => {
    get('/news-feed').then((reponse) => {
      setNewsFeed(newsFeedResponse.data);
    });
  }, []);

  const [friends, setFriends] = useState(null);
  useEffect(() => {
    get('/friends').then((response) => {
      setFriends(friendsResponse.data);
    });
   }, []);

  return (
    <div className='App'>
      <h1>My Network</h1>
      {!menu ? <p>Loading..</p> : (
        <nav>
          {menu.map((menuItem) => (
            <button key={menuItem}>{menuItem}</button>
          ))}
        </nav>
      )}
      <div className='content'>
        {!newsFeed ? <p>Loading..</p> : (
          <section>
            {newsFeed.map(({ id, title, message, imgSrc }) => (
              <article key={id}>
                <h3>{title}</h3>
                <p>{message}</p>
                <img src={imgSrc} alt='' />
              </article>
            ))}
          </section>
        )}
        {!friends ? <p>Loading..</p> : (
          <aside>
            <ul>
              {friends
                .sort((a, b) => (a.isOnline && !b.isOnline ? -1 : 0))
                .map(({ id, name, isOnline }) => (
                  <li key={id} className={isOnline ? 'online' : 'offline'}>
                    {name}
                  </li>
                ))}
            </ul>
          </aside>
        )}
      </div>
    </div>
  );
}

1 Like
useEffect(() => {
  const handleMove = (event) => ...

Why is an event handler being defined in useEffect()?

1 Like

Perhaps it has to do with the fact that this particular useEffect is being called with an empty dependency array. This means that the effect doesn’t get called after every render. The effect is only called once i.e. after the first render. Similarly, the cleanup function is also called once i.e. after the last render. Since the handleMove event handler is not being used elsewhere and the useEffect is only going to get triggered just once, so the definition of the event handler is not going to happen multiple times. Packaging the definition with the effects works adequately for this particular case. If the dependency array was omitted or a non-empty dependency array was used, then defining the event handler within the useEffect would not be suitable because the useEffect would be triggered multiple times.

1 Like
friends.sort((a, b) => (a.isOnline && !b.isOnline ? -1 : 0))

what is the meaning of the line above? why -1 and 0?

If we look at the documentation for the sort method, we can see that the sort method can be called in different ways such as making use of arrow functions and compare functions.

In the documentation, we can see this remark about the return values.

Coming back to the code posted by you, I could be wrong but I don’t think the code works as intended. I am assuming the intention is to sort the friends array such that the online friends are moved to the beginning of the array while the offline friends are moved farther down the array. Consequently, when the friends list is rendered, the online friends will appear on top while the offline friends will appear at bottom.

The problem with the code
friends.sort((a, b) => (a.isOnline && !b.isOnline ? -1 : 0))
is that there are four situations.
i) a is online, b is offline
ii) a is offline, b is online
iii) a and b are both online
iv) a and b are both offline
I don’t think that this code handles condition ii) properly.

In my opinion, this code will fix it:
friends.sort((a, b) => (b.isOnline && !a.isOnline ? 1 : 0))
This works because it evaluates to TRUE for situation ii and returns 1. This means the online friend is swapped to an earlier position in the array while the offline friend falls towards the back of the array. For situations i, iii and iv, the condition evaluates to FALSE and returns 0 which means leave the friends in their current positions. This is acceptable for situation i as well, because the online friend is already in the correct position in the array with respect to the offline friend and a swap is not needed.

Indeed if we make this edit and run the code, you will see that the online friends (green dots) appear at the top of the friends list while the offline friends (red dots) appear towards the bottom.

I could be wrong, but that is my opinion.

My code passed all the checks. But the output is a bit strange. The news feeds are empty, but then to the right I have a list of names. Very strange. Not sure if the data has changed, or there is some small subtle difference between my code and the solution.

On further investigation I believe this is how it should be looking :rofl: :joy:

Random question:

Early on in the course, it stated that a JSX expression must have exactly one outermost element.

In this case, I assume the outermost element is “div className=‘App’”. But within that there’s another div. (theres a div called “App” and a div called “content”). Shouldnt there be errors regarding this? However, everything works and is fine when the notes said that JSX expressions can have only one outermost element. Theres two here.

Can someone clarify this point?
Thanks

<div className='content'> is nested within the <div className='App'> so that you have a structure like

return (
<div className='App'>
  ...stuff...
  <div className='content'>
      ...more stuff...
  </div>
</div>
);

If you had a structure like:

return (
<div className='App'>
  ...stuff...
 </div>
  
<div className='content'>
   ...more stuff...
</div>
);

then it would be in violation of the rule mentioned in the exercise namely “The first opening tag and the final closing tag of a JSX expression must belong to the same JSX element!”

1 Like

Thanks for the explanation. Is there an easy way to figure out which opening

tag goes with which closing
tag? I assume the only way is to minimize the divs by clicking on the triangles next to the numbers (i.e. the line numbers)? Sometimes there’s a lot of divs so it gets confusing which ones goes together.

What’s the point in having 3 separate useEffects if they’re all only called when the component is mounted? Why not put them all under one hook if they’re going to only be called once?

The last task says to group the states to their corresponding effects, so I assumed they meant to put the state variables inside the useEffect dependency arrays like so:

  useEffect(() => {
    get('/menu').then(menuResponse => {
      setMenu(menuResponse.data);
    })
  }, [menu])

And the same for the other two states. But no, they just meant to declare the states right above their corresponding effect hooks…what’s going on?

All I got to say is that … what happened to the seperation of concerns!!!

I could understand that to keep it simple for a newbie, pile everything into one resource.

But I figured that since this exercise is including a couple of different components, each working in tandem…

Ohh, my brain. :face_with_spiral_eyes:

1 Like

Hi
Within the callback function of useEffect(), there is a ‘get()’ function:

useEffect(() => {
get(‘/menu’).then((response) => {
setData((prev) => ({ …prev, menuItems: response.data }));
});

[…]

}, );

Could someone explain how this works? Thanks!