R
R
rusrich2021-02-03 12:52:05
JavaScript
rusrich, 2021-02-03 12:52:05

How to execute sequentially asynchronous functions in React?

Good afternoon.

I have two asynchronous functions that receive data via fetch.
The first function receives data and writes to State.
The second function receives data based on the data written by the first function in the State and writes it to another State.

When the page is loaded, the data from the first function in the state is from the second one.
If you make changes in the code and the server restarts, then the data from the second function appears in the state.

Suggest a solution.

Code below:

import React, { useEffect, useState } from 'react';
import { getCategories, getCollections, singleCategory } from "../../actions/category";
import Link from "next/link";

const Collect = ({ router }) => {
  const [ categories, setCategories ] = useState([])
  const [ collections, setCollections ] = useState([])
  const [ values, setValues ] = useState({
    error: '',
    success: '',
    loaded: false
  })

  useEffect(() => {
    initCategories()
    getCollect()

  }, [])


  const initCategories = () => {
    getCategories().then(data => {
      if (data.error) {
        setValues({ ...values, error: data.error })
      } else {
        setCategories(data)
        setValues({ ...values, loaded: true })
        console.log(categories)
      }
    })
    // getCollect()
  }

  const getCollect = () => {
    if(categories) {
      let mov = []
      categories.map((c, i) => {
        getCollections(c.slug, 6).then(data => {
          if (data.error) {
            console.log(data.error)
          } else {
            mov.push({ name: data.category.name, movies: data.movies })
          }
        })
      })
      setCollections(mov)
    } else {
      console.log('Categories are empty')
    }
  }


  return (
    <>
      <div></div>
    </>
  );
}


export default Collect;

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Anton Romankov, 2021-02-03
@romant094

You can do this:

const initCategories = async () => {
  try {
    const data = await getCategories()
    const collect = await getCollect(data)
    setCategories(data)
    setValues({ ...values, loaded: true })
  } catch (error) {
    setValues({ ...values, error })
  }
}

const getCollect = async data => {
  return await fetch('https://site.com')
}

I did not rewrite everything exactly, but the essence, I think, is clear.

R
rusrich, 2021-02-04
@rusrich

Did so.
In the end, everything works as it should, but I can’t render, as if the showMoviesOfCollections(data.movies) function does not return anything.
The console data is correct.
How can the situation be corrected?

import React, { useEffect, useState } from 'react';
import Cardstyle from "../../components/movie/cardstyle";
import { getCategories, getCollections, singleCategory } from "../../actions/category";
import Link from "next/link";

const Collect = ({ router }) => {
  const [ categories, setCategories ] = useState([])
  const [ values, setValues ] = useState({
    error: '',
    success: '',
    loaded: false
  })

  useEffect(() => {
    initCategories()
  }, [])

  const initCategories = () => {
    return getCategories().then(data => {
      if (data.error) {
        setValues({ ...values, error: data.error })
      } else {
        setCategories(data)
      }
    })
  }

  const getCollect = (slug, limit) => {
    getCollections(slug, limit).then(data => {
      if (data.error) {
        console.log(data.error)
      } else {
        console.log(data.movies)
        return showMoviesOfCollections(data.movies)
      }
    })
  }

  const showMoviesOfCollections = (movies) => {
    return movies.map((movie, i) => {
      return (
        <div key={ i } className="col-6 col-sm-6 col-md-4 col-xl-2 mt-5 mb-5 mb-xl-0">
          <Cardstyle movie={ movie }/>
        </div>
      )
    })
  }

  const viewCollection = () => {
    return categories.map((cat, i) => {
      return (
        <div key={ i } className="bg-gray-1100 dark">
          { getCollect(cat.slug, 6) }
        </div>
      )
    })
  }

  return (
    <>
      { viewCollection() }
    </>
  );
}


export default Collect;

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question