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

React Router Dom V6同组件路由导航时useState状态未重置问题

React Router Dom V6同组件路由切换状态未重置的解决方案

问题场景

创建和编辑用户共用UserForm组件,对应路由为/user(创建)和/user/:id(编辑)。从编辑路由导航到创建路由时,组件内useState状态未重置,仍保留编辑页面的值;仅刷新页面时状态才会正常初始化。

路由配置:

<Route path='user/:id' element={<UserForm />} />
<Route path='user' element={<UserForm />} />

组件核心代码:

const UserForm = () => {
  const navigate = useNavigate();
  const params = useParams<FormParams>();
  const [loading, setLoading] = useState<boolean>(true);
  const [message, setMessage] = useState<MessageProps>();
  const [data, setData] = useState<UserModel>(newData);
  // ...其他逻辑
}

导航函数:

const newForm = () => {
  try {
    navigate('/user');
  } catch (error) {
    console.log("ERROR");
  }
}

问题原因

React Router切换同组件实例的路由时,不会执行卸载-重新挂载流程,而是复用已有组件实例,因此useState初始值仅在第一次挂载时生效,后续路由切换不会重新初始化状态。

解决方案

1. 给组件添加key属性强制重新挂载

通过给路由中的UserForm设置唯一key(基于路由路径或参数),让React识别为不同组件实例,触发卸载-重新挂载以重置状态:

<Route path='user/:id' element={<UserForm key={window.location.pathname} />} />
<Route path='user' element={<UserForm key={window.location.pathname} />} />

或精准根据参数设置key:

const UserFormRoute = () => {
  const params = useParams<FormParams>();
  return <UserForm key={params.id ?? 'create'} />;
};

<Route path='user/:id' element={<UserFormRoute />} />
<Route path='user' element={<UserForm key='create' />} />

2. 监听路由变化手动重置状态

在UserForm组件中用useEffect监听路由参数或路径变化,手动重置状态:

const UserForm = () => {
  const navigate = useNavigate();
  const params = useParams<FormParams>();
  const [loading, setLoading] = useState<boolean>(true);
  const [message, setMessage] = useState<MessageProps>();
  const [data, setData] = useState<UserModel>(newData);

  // 监听路由id参数变化,重置创建页面状态
  useEffect(() => {
    if (!params.id) {
      setData(newData);
      setMessage(undefined);
      setLoading(true);
    }
    // 编辑页面可在此添加加载用户数据逻辑
  }, [params.id]);

  // ...其他逻辑
}

若需每次路由切换都重置状态,可加入location.pathname作为依赖:

import { useLocation } from 'react-router-dom';

const UserForm = () => {
  const location = useLocation();
  // ...

  useEffect(() => {
    setData(newData);
    setMessage(undefined);
    setLoading(true);
  }, [location.pathname]);
}

3. 拆分组件复用逻辑(可选)

将创建、编辑拆为独立组件,通过自定义Hook复用核心逻辑,路由切换时组件重新挂载自然初始化状态:

// 抽离表单逻辑的自定义Hook
const useUserFormLogic = (userId?: string) => {
  const [loading, setLoading] = useState<boolean>(true);
  const [message, setMessage] = useState<MessageProps>();
  const [data, setData] = useState<UserModel>(newData);

  useEffect(() => {
    if (userId) {
      // 加载编辑用户数据
      fetchUserById(userId).then(res => {
        setData(res);
        setLoading(false);
      });
    } else {
      // 创建页面重置数据
      setData(newData);
      setLoading(false);
    }
  }, [userId]);

  // 提交表单等逻辑
  const handleSubmit = () => { /* ... */ };

  return { loading, message, data, setData, handleSubmit };
};

// 创建用户组件
const CreateUserForm = () => {
  const formLogic = useUserFormLogic();
  return <UserFormUI {...formLogic} />;
};

// 编辑用户组件
const EditUserForm = () => {
  const params = useParams<FormParams>();
  const formLogic = useUserFormLogic(params.id);
  return <UserFormUI {...formLogic} />;
};

// 路由配置
<Route path='user/:id' element={<EditUserForm />} />
<Route path='user' element={<CreateUserForm />} />

内容的提问来源于stack exchange,提问作者Lucas K C

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 13:17:03