Home > front end >  React: How to avoid duplication in a state array
React: How to avoid duplication in a state array

Time:08-02

I am making MERN social media app.

I want to show all the friends of the current user in a list in SideBar.jsx .

Home.jsx (parent of Sidebar.jsx)

import React, { Component } from "react";
import { Person } from "@material-ui/icons";
import Topbar from "../../components/topbar/Topbar";
import Sidebar from "../../components/sidebar/Sidebar";
import Feed from "../../components/feed/Feed";
import Rightbar from "../../components/rightbar/Rightbar";
import "./home.css";
export default function Home() {
  return (
    <>
      <Topbar />
      <div className="homeContainer">
        <Sidebar />
        <Feed />
        <Rightbar />
      </div>
    </>
  );
}

SideBar.jsx

import "./sidebar.css";
import React, { Component, useContext, useState } from "react";
...
import { axiosInstance } from "../../config";

export default function Sidebar() {
  const { user } = useContext(AuthContext);
  const [followings, setFollowings] = useState([]);
  const followingsList = user.followings;
  useEffect(() => {
    const fetchFollowings = async () => {
      followingsList.map(async (id) => {
        try {
          const theUser = await axiosInstance.get(`/users?userId=${id}`);
          if (followings.includes(theUser.data)) {
          } else {
            setFollowings((prev) => [...prev, theUser.data]);
          }
        } catch (error) {
          console.log(error);
        }

      });
    };
    fetchFollowings();
  }, [user]);
  return (
    <div className="sidebar">
  .....
        <ul className="sidebarFriendList">
          {followings.map((u) => (
            <CloseFriend key={u._id} user={u} />
          ))}
        </ul>
      </div>
    </div>
  );
}


For example, in this case, in the state "followings", there are 2 user objects.

So, the line

 followings.map((u) => (...

should only show 2 entries.

However, the result is below.

enter image description here

As you can see, it is showing each friend twice. I tired to check if a user object already exists in followings by doing

 if (followings.includes(theUser.data)) {
          } else {
            setFollowings((prev) => [...prev, theUser.data]);
          }

But this is not working.

How can I make sure that it only shows each user once?

I want it to be like this enter image description here

Any help would be greatly appreciated. thank you

CodePudding user response:

This is happening because it seems that your useEffect method is being fired two times (probably because you are using React.StrictMode) and you are setting the state inside the .map method (that is not good because you trigger a new render each time you call the setState).

What I would recommend you to do, is to remove the setState from the .map method and just set the new state after you format your data. So it would be something like this:

const newFollowings = followingsList.map(async (id) => {
  try {
    const theUser = await axiosInstance.get(`/users?userId=${id}`);
    return theUser.data;
  } catch (error) {
    console.log(error);
  }
});

setFollowings(newFollowings);

Probably you would have to add a filtering to the array in case there are some errors (because on errors the mapped value would be undefined):

.filter(data => data);

CodePudding user response:

When you are using the .map function with async/await Promise.all usually always does the trick. Instead of pushing the state on every iteration you collect the followers list and set the state when all your fetching is done. I did not test it yet, but I hope it works.

const followingsList = user.followings;

useEffect(() => {
    const fetchFollowings = async () => {
      const list = await Promise.all(followingsList.map(async (id) => (
        await axios.get('/user?userId='   id);
      )));
      
      setFollowers(list);
    };
    fetchFollowings();
  }, [user]);

Note: let me know if it works, if not I'll do a little sandbox on my own

  • Related