【问题标题】:How can I escape React useEffect infinite loop?如何逃脱 React useEffect 无限循环?
【发布时间】:2021-08-07 08:14:51
【问题描述】:

我写了一段代码,通过 React Hook 接收 api 并在点击时通过传递 id 在子组件中再次调用该 api。但是子组件的useEffect或者onClick中的箭头函数setState好像有问题。

如果您能回答我如何解决它,我将不胜感激。

Users.js

import axios from 'axios';
import React, { useState, useEffect } from 'react';
import UserInfo from './UserInfo';


function Users() {
    const [users, setUsers] = useState(null)
    const [loding, setLoding] = useState(false)
    const [error, setError] = useState(false)


    const [userId, setUserId] = useState(null)

    const fetchUsers = async () => {
        try {
            setUsers(null)
            setError(null);
            setLoding(true)

            const respnse = await axios.get('https://jsonplaceholder.typicode.com/users')

            setUsers(respnse)
        } catch (e) {
            setError(e)
        }
        setLoding(false)
    };

    useEffect(() => {
        fetchUsers();
    }, []);

    if (loding) return <div>loading...</div>
    if (error) return <div>error....</div>
    if (!users) return null;

    return (
        <>
            <ul>
                {
                    users.data.map(user =>
                        <li key={user.id} onClick={() => setUserId(user.id)} >
                            {user.username} ({user.name})
                        </li>
                    )
                }
            </ul>
            <button onClick={fetchUsers}>
                reload
            </button>
            {userId && <UserInfo id={userId} />}
        </>
    );
}

export default Users;

UserInfo.js

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

function UserInfo({ id }) {

    const [userInfo, setUserInfo] = useState(null)

    async function getUsersAPI() {
        try {
            const response = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`)
            setUserInfo(response)
        } catch (e) {

        }
    }

    useEffect(() => {
        getUsersAPI()
    }, [userInfo])


    if (!userInfo) {
        return null;
    }

    const { data } = userInfo

    return (
        <>
            <h2>{data.username}</h2>
            <p>
                <b>email: </b>{data.email}
            </p>
        </>
    );
}

export default UserInfo;

【问题讨论】:

  • 为什么userInfouseEffect 的依赖数组中?
  • 实现了可以通过api获取useinfo信息。如果我错了,请给我另一个答案。
  • getUsersAPI 更新userInfo 状态,作为依赖,触发useEffect 钩子的回调再次调用getUsersAPI,从而创建一个渲染循环。您实际上希望孩子的效果何时运行?如果我不得不猜测,它应该是传递的 id 属性,因为它在 getUsersAPI 调用中被引用。

标签: javascript reactjs react-hooks use-effect


【解决方案1】:

您似乎希望 id 成为 useEffect 依赖项而不是 userInfo.

否则每次userInfo 更改时,效果都会运行,它会调用getUsersAPI,而userInfo 在axios 解析时会依次设置userInfo 的值(从而导致无限循环)。

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

    function UserInfo({ id }) {
        const [userInfo, setUserInfo] = useState(null)
        async function getUsersAPI() {
            try {
                const response = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`)
                setUserInfo(response)
            } catch (e) {}
        }

        useEffect(() => {
            getUsersAPI()
        }, [id])

        if (!userInfo) {
            return null;
        }

        const { data } = userInfo

        return (
            <>
                <h2>{data.username}</h2>
                <p>
                    <b>email: </b>{data.email}
                </p>
            </>
        );
    }

    export default UserInfo;

【讨论】:

    【解决方案2】:

    这个问题是由于您将userInfo 设置为useEffect 依赖数组的依赖!每次这个组件渲染时,useEffect 都会调用你的 API,它会改变 userInfo 的值,所以你会遇到无限循环!

    【讨论】:

      【解决方案3】:

      问题出在 UserInfo.js 文件中。 在这些行中:

      useEffect(() => {
          getUsersAPI()
      }, [userInfo])
      

      您获取了 userInfo,但随后又获取了 setUserInfo(response),这导致 useEffect 再次运行。

      如果可能想保留为:

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

      所以 useEffect 只运行一次。 或者你想让它从 props 中反映你的最后一个 userId,然后将 userId 放到依赖数组中:

      useEffect(() => {
          getUsersAPI()
      }, [id])
      

      【讨论】:

        猜你喜欢
        • 2022-01-23
        • 1970-01-01
        • 2021-01-31
        • 2020-04-14
        • 2020-09-06
        • 2019-08-15
        • 2021-10-21
        • 2021-11-01
        相关资源
        最近更新 更多