Эффект реакции бесконечное повторное рендеринг при получении данных - PullRequest
0 голосов
/ 01 ноября 2019

Я хочу получить массив из бэкэнда, используя Provider, Context и useEffect:

import React, {useState, useEffect} from 'react'

const UsersContext = React.createContext()

const fetchUsers = async () => {
  const url = 'http://localhost:3000/users'
  const response = await fetch(url)
  console.log('response', await response.json())
  return response
}

export const UsersProvider = ({children}) => {
  // state
  const [users, setUsers] = useState([])

  // query data
  const data = fetchUsers()
  console.log('data', data)

  // component updates
  useEffect(() => {
    if (data) {
      // setUsers(data)
    }
  }, [data])

  return (
    <UsersContext.Provider value={users}>
      {children}
    </UsersContext.Provider>
  )
}

Если я установлю пользователей, как только получу данные из бэкэнда, я получу бесконечный повторный рендер,Проблема в том, что данные всегда обещают, хотя я вижу ответ после вызова:

В методе fetchUsers:

console.log('response', await response.json())
{users: Array(1)}
users: Array(1)
0:
created_at: "2019-10-09T17:41:21.818Z"
email: "ash@email.com"
id: 1
name: "ash"
password_digest: "dafasfae"
updated_at: "2019-10-09T17:41:21.818Z"

В UsersProvider:

console.log('data', data)
Promise {<pending>}
__proto__: Promise
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: Response
body: (...)
bodyUsed: true
headers: Headers {}
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://localhost:3000/users"
__proto__: Response

Ответы [ 3 ]

1 голос
/ 01 ноября 2019

Я бы переместил функцию fetchUsers внутри эффекта и попробовал бы так:

import React, { useState, useEffect } from "react";

const UsersContext = React.createContext();

export const UsersProvider = ({ children }) => {
  // state
  const [users, setUsers] = useState([]);

  // component mounts
  useEffect(() => {
    const fetchUsers = async () => {
      const url = "http://localhost:3000/users";
      const response = await fetch(url);
      const usersData = await response.json();
      setUsers(usersData);
    };
    fetchUsers();
  }, []);

  return (
    <UsersContext.Provider value={users}>{children}</UsersContext.Provider>
  );
};

Вот очень хороший пост о получении данных с помощью ловушек реагирования:

https://www.robinwieruch.de/react-hooks-fetch-data

0 голосов
/ 01 ноября 2019

Ваша выборка данных должна происходить внутри вызова useEffect. Сейчас происходит то, что каждый раз, когда ваш компонент рендерит, вы заново выбираете список пользователей, что вызывает изменение объекта данных и вызывает повторный рендеринг. Приведенный ниже код извлекает данные только при монтировании компонента.

useEffect(() => {
    let canceled = false;

    const fetchData = async () => {
        const users = await fetchUsers();

        if (!canceled && data) {
            setUsers(data);
        }
    };

    fetchUsers();

    return () => { canceled = true; }
}, []);
0 голосов
/ 01 ноября 2019

вернуть только данные

const fetchUsers = async () => {
  const url = 'http://localhost:3000/users'
  const response = await fetch(url)
                         .then( data => {
                             return data
                           })
                         .catch(err=>console.log(err));
  return response;
}

надеюсь, это поможет вам.

...