You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用useState异步更新引发Web应用无限重渲染的解决方法

解决React组件无限重渲染与异步数据获取问题

问题根源

你直接在组件函数体内调用setPosts,组件每次渲染时都会执行这段代码:状态更新触发组件重新渲染,重新渲染后又会再次调用setPosts,形成无限循环。

同时你的getPost函数存在疏漏:没有返回创建的Promise对象,导致await getPost无法正确等待异步请求完成,最终getPosts返回的结果不符合预期。

修复步骤

1. 使用useEffect包裹数据获取逻辑

引入useEffect,将数据获取和状态更新放在useEffect回调中,并设置合适的依赖项,确保只在组件挂载(或依赖变化)时执行一次。

修改后的App.jsx代码:

import React, { useState, useEffect } from 'react';
import './App.css';
import Nav from './Navbar/NavBar.jsx';
import Content from "./content/Content"
import { getPosts } from "./api/post";

function App() {
    const idList = ["631a58c165b3a10ac71497e1", "631a58fa65b3a10ac71497e3"];
    const [posts, setPosts] = useState([]);

    useEffect(() => {
        // 定义异步函数处理数据获取
        const fetchPosts = async () => {
            try {
                const fetchedPosts = await getPosts(idList);
                setPosts(fetchedPosts);
            } catch (err) {
                console.error('获取文章失败:', err.message);
            }
        };

        fetchPosts();
    }, [idList]); // 依赖项:仅当idList变化时重新执行

    return (
        <div>
            {posts.length > 0 ? 
                posts.map(post => <div key={post._id}>{post.title}</div>) 
                : '加载中...'}
        </div>
    );
}

export default App;

2. 修复getPost函数的Promise返回问题

修改getPost函数,让它返回创建的Promise对象,确保await能正常等待异步请求完成:

import axios from "axios";

const getPost = (id) => {
    // 返回Promise对象
    return new Promise((resolve, reject) => {
        const url = "/posts/" + id;
        console.log(url);
        axios.get(url)
            .then(response => {
                if (response.status === 200){
                    console.log("Succesfull call");
                    console.log(response.data);
                    resolve(response.data);
                }
                else if(response.status === 404){
                    reject(response);
                }
            })
            .catch(err => {
                console.log("Failed call");
                reject(err);
            });
    });
};

const getPosts = async (idList) => {
    var result = [];
    // 用for...of替代for...in,避免遍历数组索引属性
    for(const id of idList){
        try{
            let post = await getPost(id);
            result.push(post);
        }catch(err){
            console.log(err.message);
        }
    }
    
    if (result.length === 0) throw {message: "No posts"};
    else return result;
};

export {getPosts};

额外优化点

  • 用for...of替代for...in遍历数组,避免意外遍历到数组的原型链属性或索引键。
  • 在useEffect中添加错误捕获,避免请求失败导致组件报错。

内容的提问来源于stack exchange,提问作者Bot Ellis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:51:18