Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With a React Hook, trying to fetch multiple datas using forEach

I'm trying to get data from the Figma API but unfortunately I can't do it in one call. I first need to get the list of all projects in a team and then for each project, get the list of files.

Here is the code I made to do that:

  const [projects, setProjects] = useState([]);
  const [files, setFiles] = useState([]);

  useEffect(() => {
    const fetchProjects = async () => {
      const result = await axios(
        `https://api.figma.com/v1/teams/${teamId}/projects`, {
          headers: { 'Authorization': `Bearer ${token}` }
        });
      setProjects(result.data.projects);
    };

    fetchProjects();
  }, []);

  useEffect(() => {
    projects.forEach(project => {
      const fetchFiles = async () => {
        const result = await axios(
          `https://api.figma.com/v1/projects/${project.id}/files`, {
            headers: { 'Authorization': `Bearer ${token}` }
          });

        setFiles([ ...files, {
          projectName: project.name,
          files: result.data.files
        }])
      };

      fetchFiles();
    })
  }, [projects]);

I explicitly only put projects as a dependency on the second useEffect as otherwise it will create a lot of different render and I only want to loop in the list of projects.

In my Figma team I have 4 projects. Each of these have from 1 to 5 files. I would like my state files to have 4 objects that contains the name of the project and the list of files that it contains.

The problem that I have today is first that I have some warnings from React saying that I need to put the other dependencies and second that my files state is only populated with the latest project and not all 4 of them.

like image 223
Charles de Dreuille Avatar asked Nov 06 '22 14:11

Charles de Dreuille


1 Answers

As far as state is concerned, you are getting this issue since you are trying to update state in a loop based on the closure variable. Instead, you can use the callback pattern to update state. This will also not warn you for adding files as a dependency to useEffect.

Also you could move out the fetchFiles function outside of the loop.

Also you may choose to add the setFiles method as a dependency or disable the warning as it won't affect your code. setFiles function won't change within the scope of your code

const [projects, setProjects] = useState([]);
  const [files, setFiles] = useState([]);

  useEffect(() => {
    const fetchProjects = async () => {
      const result = await axios(
        `https://api.figma.com/v1/teams/${teamId}/projects`, {
          headers: { 'Authorization': `Bearer ${token}` }
        });
      setProjects(result.data.projects);
    };

    fetchProjects();
  }, []);

  useEffect(() => {
    const fetchFiles = async (id, name) => {
        const result = await axios(
          `https://api.figma.com/v1/projects/${id}/files`, {
            headers: { 'Authorization': `Bearer ${token}` }
          });

        setFiles(prevFiles => ([ ...prevFiles, {
          projectName: name,
          files: result.data.files
        }]))
      };
    projects.forEach(project => {
      fetchFiles(project.id, project.name);
    })
  }, [projects]);
like image 189
Shubham Khatri Avatar answered Nov 15 '22 07:11

Shubham Khatri