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

React组件无限循环加载故障 如何使其仅依据数据库返回数据触发加载

问题根源

你的代码里存在两处触发无限渲染的逻辑:

  • Added组件中,useEffect的依赖项设置为data,但useEffect内部调用setData会修改data的值,导致每次请求完成后都会重新触发useEffect,形成死循环。
  • App父组件中,useEffect直接对state.list赋值(属于直接修改useReducer的状态,违反React状态不可变原则),同时该useEffect的依赖项设置为state.list,修改state.list后会重新触发useEffect,形成第二处死循环。

修复方案

1. 修复Added组件

把useEffect的依赖项改为空数组,让它只在组件首次挂载时触发请求即可;如果需要数据更新时重新请求,可以改为依赖父组件传入的更新标识:

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

function Added() {
  const [data, setData] = useState([]);

  // 依赖改为空数组,仅首次挂载执行
  useEffect(() => {
    Axios.get("http://localhost:3001/").then((result) => {
      setData(result.data);
    }).catch(err => console.log(err));
  }, []);

  console.log("1");

  return data.map((item) => {
    return (
      <div key={item._id}>
        <h1>{item.finame}</h1>
        <h1>{item.laname}</h1>
        <h5>{item.age}</h5>
      </div>
    );
  });
}

export default Added;

2. 修复App父组件

删除直接修改state.list的useEffect,调整useReducer的初始值,不要把异步函数直接放到初始state里:

import "./App.css";
import { useState, useReducer, useEffect } from "react";
import Added from "./added";
import Axios from "axios";

function App() {
  /* -------------------- For the useReducer -------------------- */
  const Actions = {
    Add: "add",
    SetList: "setList"
  };

  // 初始值设为空数组
  const defaultState = {
    list: [],
  };

  const reducer = (state, action) => {
    switch (action.type) {
      case Actions.Add:
        const listItem = action.payload;
        try {
          Axios.post("http://localhost:3001/add", listItem);
        } catch (error) {
          console.log(error + "444444");
        }
        return { ...state, list: [...state.list, listItem] };
      case Actions.SetList:
        return { ...state, list: action.payload };
      default:
        console.log("this is the default");
        return state;
    }
  };

  const [state, dispatch] = useReducer(reducer, defaultState);

  // 首次挂载拉取列表数据,通过dispatch更新state,不要直接修改
  useEffect(() => {
    Axios.get("http://localhost:3001/").then((result) => {
      dispatch({type: Actions.SetList, payload: result.data})
    }).catch(err => console.log(err));
  }, []);

  /* ---------------------------- For the form ---------------------------- */
  const [listItem, setListItem] = useState({ finame: "", laname: "", age: 0 });

  const handelChange = (e) => {
    const name = e.target.name;
    const value = e.target.value;
    setListItem({ ...listItem, [name]: value });
  };

  const handelSubmit = (e) => {
    e.preventDefault();
    dispatch({ type: Actions.Add, payload: listItem });
  };

  /* ------------------------ for the form return ---------------------- */
  return (
    <div className="App">
      <h1>CRUD app using MERN stack</h1>

      <form onSubmit={handelSubmit}>
        <label htmlFor="finame">First name:</label>
        <input
          type="text"
          name="finame"
          id="finame"
          value={listItem.finame}
          onChange={handelChange}
        />

        <label htmlFor="laname">Last name:</label>
        <input
          type="text"
          name="laname"
          id="laname"
          value={listItem.laname}
          onChange={handelChange}
        />

        <label htmlFor="age">Age:</label>
        <input
          type="Number"
          name="age"
          id="age"
          value={listItem.age}
          onChange={handelChange}
        />

        <button type="Submit">Submit</button>
      </form>

      {state.list.length > 0 && <Added />}
    </div>
  );
}

export default App;

额外优化建议

  • 父子组件不要重复请求同一个接口,你可以把列表数据从App组件通过props传给Added组件,减少不必要的网络请求。
  • 提交数据的post请求是异步操作,建议等待请求成功后再更新本地state,避免本地数据和服务端数据不一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 08:24:00