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

React中useLocation传数据到useState引发无限循环的解决方案

解决React Router通过location.state传参后追加数据导致的无限循环问题

我明白你遇到的问题了——直接在组件渲染流程里调用setUsers处理路由传来的location.state,会触发组件重渲染,而重渲染又会再次执行这段逻辑,最终陷入无限循环。咱们用useEffect就能完美解决这个问题,下面一步步来:

问题根源

你现在的代码里,这段逻辑是在组件每次渲染时都会执行的:

if (location.state !== null) {
  setUsers([...users, location.state]);
  location.state = null;
}

每次调用setUsers都会更新组件状态、触发重新渲染,而重渲染后又会重新检查location.state(另外直接修改location.state是无效的,因为useLocation返回的是路由维护的不可变对象),所以就陷入了无限循环。

解决方案:用useEffect监听location.state

把处理路由传参的逻辑放到useEffect中,只在location.state有值的时候执行一次,并且用navigate.replace清除路由状态,避免用户刷新页面后重复添加数据。

修改后的List组件代码:

import React, { useEffect, useState } from "react";
import "../style.css";
import { useNavigate, useLocation } from "react-router-dom";

export default function List() {
  const [users, setUsers] = useState([]);
  const navigate = useNavigate();
  const location = useLocation();

  // 从API获取初始用户数据
  useEffect(() => {
    async function fetchData() {
      const response = await fetch(
        "https://jsonplaceholder.typicode.com/users"
      );
      const data = await response.json();
      setUsers(data);
    }
    fetchData();
  }, []);

  // 处理路由传来的新用户数据
  useEffect(() => {
    // 校验state是否为有效用户对象,避免空值或错误数据
    if (location.state?.name && location.state?.email && location.state?.website) {
      // 使用函数式更新,确保拿到最新的users状态
      setUsers(prevUsers => [...prevUsers, location.state]);
      // 用replace清除路由state,避免刷新/后退时重复处理
      navigate(0, { replace: true, state: null });
    }
  }, [location.state, navigate]);

  function onClickHandler(e) {
    navigate("/Form");
  }

  return (
    <>
      <div className="container">
        <h1>Contacts</h1>
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Email</th>
              <th>Website</th>
            </tr>
          </thead>
          <tbody>
            {users.map((user, index) => {
              return (
                <tr key={index}>
                  <td>{user.name}</td>
                  <td>{user.email}</td>
                  <td>{user.website}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      <button onClick={onClickHandler}>Add Contact</button>
    </>
  );
}

关键说明:

  1. 函数式更新state:用setUsers(prevUsers => [...prevUsers, location.state])而非直接使用users数组,这样能确保我们总是基于最新的状态进行更新,避免闭包导致的旧状态问题。
  2. useEffect依赖控制:把location.state和navigate加入依赖数组,这样只有当location.state变化时,这个effect才会执行,避免不必要的重复触发。
  3. 清除路由state:用navigate(0, { replace: true, state: null })替换当前路由的状态,这样用户刷新页面或后退再前进时,不会再次触发添加逻辑,因为state已经被清空了。

这样修改后,就能安全地把Form组件传来的用户数据追加到列表里,而且不会出现无限循环的问题啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 10:05:23