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

如何在React Router 6中进行状态提升?路由间状态共享咨询

路由间状态共享的解决方案

你的判断是对的,需要把共享状态提升到App组件(而非Layout),原因和具体实现方式如下:

为什么选App而非Layout?

你的Layout组件仅负责渲染Header和Outlet,它本质是布局容器,并不直接包裹ContactList和AddContact这两个路由组件——这两个组件是通过Outlet动态渲染的。而App是这两个组件的最顶层共同父组件,符合React状态提升的核心原则:将共享状态放在需要使用它的所有组件的最上层共同父组件中,这样能确保状态的作用域合理,且所有依赖组件都能访问到。

具体实现方式

方式1:通过props传递(适合简单场景)

你已经在App组件中定义了contacts和setContacts,直接把它们通过props传给两个路由组件即可:

function App() {
  const [contacts, setContacts] = useState([])

  return (
    <BrowserRouter>
      <Routes>
        <Route element={<Layout />}>
          {/* 给ContactList传入contacts用于渲染 */}
          <Route path='/' element={<ContactList contacts={contacts} />} />
          {/* 给AddContact传入setContacts用于更新状态,可选传入contacts */}
          <Route path='/add' element={<AddContact setContacts={setContacts} contacts={contacts} />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

在AddContact中调用setContacts更新状态:

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

function AddContact({ setContacts, contacts }) {
  const navigate = useNavigate();

  const handleSubmit = (e) => {
    e.preventDefault();
    // 从表单获取新联系人数据,示例用模拟数据
    const newContact = {
      id: Date.now(),
      name: e.target.name.value,
      email: e.target.email.value
    };
    // 更新联系人列表
    setContacts([...contacts, newContact]);
    // 添加完成后跳转到列表页
    navigate('/');
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="name" placeholder="姓名" required />
      <input type="email" name="email" placeholder="邮箱" required />
      <button type="submit">添加联系人</button>
    </form>
  );
}

在ContactList中直接使用contacts渲染列表:

function ContactList({ contacts }) {
  return (
    <div className="contact-list">
      <h2>联系人列表</h2>
      {contacts.length === 0 ? (
        <p>暂无联系人</p>
      ) : (
        contacts.map(contact => (
          <div key={contact.id} className="contact-item">
            <p>姓名:{contact.name}</p>
            <p>邮箱:{contact.email}</p>
          </div>
        ))
      )}
    </div>
  );
}

方式2:使用React Context(适合复杂场景)

如果后续你的组件层级变深,或者有更多组件需要访问联系人状态,用props传递会变得繁琐,这时可以用Context来管理状态:

首先创建Context和Provider:

import { createContext, useContext, useState } from 'react';

// 创建联系人Context
const ContactContext = createContext();

// 创建Provider组件,包裹需要访问状态的组件
export function ContactProvider({ children }) {
  const [contacts, setContacts] = useState([]);

  return (
    <ContactContext.Provider value={{ contacts, setContacts }}>
      {children}
    </ContactContext.Provider>
  );
}

// 自定义Hook,简化Context的使用
export function useContacts() {
  return useContext(ContactContext);
}

然后在App中用ContactProvider包裹路由:

import { ContactProvider } from './ContactContext';

function App() {
  return (
    <ContactProvider>
      <BrowserRouter>
        <Routes>
          <Route element={<Layout />}>
            <Route path='/' element={<ContactList />} />
            <Route path='/add' element={<AddContact />} />
          </Route>
        </Routes>
      </BrowserRouter>
    </ContactProvider>
  );
}

最后在组件中通过自定义Hook获取状态:

// AddContact组件
import { useNavigate } from 'react-router-dom';
import { useContacts } from './ContactContext';

function AddContact() {
  const { contacts, setContacts } = useContacts();
  const navigate = useNavigate();

  const handleSubmit = (e) => {
    e.preventDefault();
    const newContact = {
      id: Date.now(),
      name: e.target.name.value,
      email: e.target.email.value
    };
    setContacts([...contacts, newContact]);
    navigate('/');
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* 表单内容同上 */}
    </form>
  );
}

// ContactList组件
import { useContacts } from './ContactContext';

function ContactList() {
  const { contacts } = useContacts();

  return (
    <div className="contact-list">
      {/* 渲染逻辑同上 */}
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 07:13:12