Последовательная загрузка данных в массив React приложения через useState и axios

На почти 1 день встала разработка из-за того, что сразу не сообразил про особенность работы useState, хотя с ним не первый день работаю. Нужно было сформировать массив данных в React приложении через useState и axios, который тащил данные из API с разными параметрами. Посто про мои грабли и то, как не потратить 1 день на поиск не существующего бага React.

Если в React приложении нужно получить данные из нескольких однотипных запросов и поместить их в массив при загрузке через useState и useEffect, то не надо стараться это разбить на несколько загрузок, а надо загрузить их за один цикл функции.

Я использую axios для загрузки, а в нем есть метод all. Пока не переписал загрузку на его использование, то было так – один раз открываю страницу после компиляции и все ок, перегружаю – и данные не отображаются на странице. При этом, переменные имеют нужные значения. Это связано с асинхронностью работы useState, которым я пытался последовательно обновлять данные.

После реализации через axios.all (в принципе, можно через что угодно делать, только не пытаться обновлять данные через useState, а делать все внутри тела одной функции), все заработало.

Пример кода

  const langs: string[] = ['ru', 'en', 'he', 'qq']
  const defaultContent: Map<string, ISiteObjects> = new Map<string, ISiteObjects>()
  langs.forEach(element => {
    defaultContent.set(element, emptyObject)
  })

  const [content, setContent] = useState<Map<string, ISiteObjects>>(defaultContent)
  const [isLoaded, setIsLoaded] = useState<boolean>(false)
  const mainUrl = 'https://localhost:5001/api/Lang/'

  const readdata = async (): Promise<void> => {
    const urls = langs.map(x => { return mainUrl + x })
    const requests = urls.map(async (url) => await axios.get(url))
    axios.all(requests).then(responses => {
      const data = new Map<string, ISiteObjects>()
      responses.forEach((res, i) => {
        if (data.has(langs[i])) data.delete(langs[i])
        data.set(langs[i], res.data)
      })
      setContent(data)
    }).catch(err => { console.log(err) })
  }
  useEffect(() => {
    void readdata()
    setIsLoaded(true)
  }, [])


Комментариев нет »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment







MarkiMarta.ru. Записки отца-программиста" с 2009 г.
Категория информационной продукции 18+
Яндекс.Метрика