提取数据时对效果无限重渲染

时间:2019-11-01 12:29:11

标签: reactjs fetch react-hooks

我想使用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 个答案:

答案 0 :(得分:1)

我将在效果内部移动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>
  );
};

这是一篇有关使用react挂钩获取数据的好文章:

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

答案 1 :(得分:0)

仅返回数据

    async filterFn (val, update, abort) {
      // call abort() at any time if you can't retrieve data somehow
      if (this.users.length === 0) {
        // if there is no data, fetch and cache it so it can be filtered
        await axios.get('https://jsonplaceholder.typicode.com/users')
          .then(response => {
            this.users = response.data
          })
      }
      if (val === '') {
        update(() => {
          this.options = this.users.map(user => user.username)
        })
      } else if (this.users.length === 0) {
        update(() => {
          this.options = []
        })
      } else {
        update(() => {
          this.options = this.users
            .map(user => user.username)
            .filter(name => {
              return name && name.toLowerCase().indexOf(val.toLowerCase()) !== -1
          })
        })
      }
    },

希望这会对您有所帮助。

答案 2 :(得分:0)

您的数据提取需要在useEffect调用内进行。现在发生的事情是每次渲染组件时,您都在重新获取用户列表,这导致数据对象发生更改并触发重新渲染。下面的代码仅在安装组件时才获取数据。

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

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

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

    fetchUsers();

    return () => { canceled = true; }
}, []);