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

React路由切换时列表数据无法持久化的问题求助

问题描述

我开发了一个小型React项目,表单提交用户信息后会在同一页面的表格展示,这部分功能正常。但点击Home页面再返回表单页面时,列表就空了。我希望在整个网站浏览过程中列表数据都能保留,求解决方法。


相关组件代码

App.js

import { useState } from "react";
import { Route, Routes } from "react-router-dom";
import Navbar from "./Components/Navbar";
import Home from "./Components/Home";
import PersonList from "./Components/PersonList";
import PersonDetails from "./Components/PersonDetails";
import LoginForm from "./Components/LoginForm";
import { UserContext } from "./Components/UserContext";
import "bootstrap/dist/css/bootstrap.min.css";
import "./App.css";

function App() {
  
  const [value, setValue] = useState(null);
  
  return (
    <div className="App">
      <UserContext.Provider value={{value, setValue }}>
        <Navbar />
        <div className="content">
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/PersonList" element={<PersonList />} />
            <Route path="/Components/PersonDetails/:id/*" element={<PersonDetails />} />
            <Route path="/LoginForm" element={<LoginForm />} />
          </Routes>
        </div>
      </UserContext.Provider>
    </div>
  );
}

export default App;
import { Link } from "react-router-dom";
import { UserContext } from "./UserContext";
import { useContext, useState } from "react";

export default function Navbar() {
    const {value, setValue} = useContext(UserContext);

  return (
  <nav className="navbar">
    <h1>React Assignment</h1>

    <div className="links">
      <Link to="/">Home</Link>
      <Link to="/PersonList">Person List</Link>
      { !value && <Link to="/LoginForm">Login</Link> }
      { value && <Link to="/" onClick={() => {setValue(null);}} >Logout</Link> }
      {value}
    </div>
  </nav>
  )
}

PersonList.js

import { useState } from "react";
import UserForm from "./UserForm";
import UserList from "./UserList";


const PersonList = () => {
      // create array using useState to store the contact form data.
  const [contacts, updateContacts] = useState([]);

  // update contact state.
   const addContact = (contact) => {
     updateContacts([...contacts, contact]);

  };

    return (
        <div className="personlist">
            <UserForm addContact={addContact} />
            <UserList contacts={contacts} />
        </div>
    );
}
 
export default PersonList;

UserForm.js

import { useState } from "react";
import { Form, Button } from "react-bootstrap";

// retrieve addContact function from PersonList.js as props.
export default function UserForm({ addContact }) {

  // useState hook to manage state in functional components.
  const [contactInfo, setContactInfo] = useState({
    firstname: "",
    lastname: "",
    age: "",
    nationality: "",
    email: "",
  });

  // update input fields.
  const handleChange = (event) => {
    setContactInfo({ ...contactInfo, [event.target.name]: event.target.value });
  };

  // submit data to addContact function.
  const handleSubmit = (event) => {
    event.preventDefault();
    addContact(contactInfo);
    // clear input fields after submit
    setContactInfo({
      firstname: "",
      lastname: "",
      age: "",
      nationality: "",
      email: "",
    });
  };

  return (
    <div className="form-container w-50">
      <Form onSubmit={handleSubmit}>
        <h3>Contact Form</h3>

        <Form.Control
          size="sm"
          type="text"
          name="firstname"
          placeholder="First Name"
          required
          value={contactInfo.firstname}
          onChange={handleChange}
        />

        <Form.Control
          size="sm"
          type="text"
          name="lastname"
          required
          placeholder="Last Name"
          value={contactInfo.lastname}
          onChange={handleChange}
        />

        <Form.Control
          size="sm"
          type="number"
          name="age"
          placeholder="Age"
          value={contactInfo.age}
          onChange={handleChange}
        />

        <Form.Control
          size="sm"
          type="text"
          name="nationality"
          placeholder="Nationality"
          value={contactInfo.nationality}
          onChange={handleChange}
        />

        <Form.Control
          size="sm"
          type="email"
          name="email"
          placeholder="Email"
          required
          value={contactInfo.email}
          onChange={handleChange}
        />

        <p></p>
        <Button variant="primary" size="sm" type="submit">
          Submit Contact
        </Button>
        <p></p>
      </Form>
    </div>
  );
}

UserList.js

import { Table } from "react-bootstrap";
import uuid from "react-uuid";
import { Link } from "react-router-dom";

// retrieve contacts from PersonList.js as props
export default function UserList({ contacts }) {

  if (contacts.length === 0) {
    return <h5>The list is empty</h5>;
  } else {

    return (
      <Table className="w-100" bordered hover size="sm">
        <thead>
          <tr>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
            <th>Nationality</th>
            <th>Email</th>
          </tr>
        </thead>
        <tbody className="tablelinks">
          {/* use .map to loop */}
          {contacts.map((contact) => (

            <tr key={uuid()}>
              <td>
              <Link to={`/Components/PersonDetails/${contact.firstname+contact.lastname}`}>
                {contact.firstname}
              </Link>
              </td>
              <td>{contact.lastname}</td>
              <td>{contact.age}</td>
              <td>{contact.nationality}</td>
              <td>{contact.email}</td>
            </tr>
          ))}
        </tbody>
      </Table>
    );
  }
}

解决方案

问题根源

PersonList组件内部的contacts状态会随组件卸载而丢失——当你切换到Home页面时,PersonList被卸载,状态清空;返回时组件重新挂载,contacts回到初始空数组。

修复步骤

利用已有的UserContext把联系人状态提升到App组件(全局上下文层级),确保状态不随组件卸载丢失:

  1. 修改App.js,添加联系人状态到上下文:
import { useState } from "react";
import { Route, Routes } from "react-router-dom";
import Navbar from "./Components/Navbar";
import Home from "./Components/Home";
import PersonList from "./Components/PersonList";
import PersonDetails from "./Components/PersonDetails";
import LoginForm from "./Components/LoginForm";
import { UserContext } from "./Components/UserContext";
import "bootstrap/dist/css/bootstrap.min.css";
import "./App.css";

function App() {
  const [value, setValue] = useState(null);
  // 添加全局联系人状态
  const [contacts, setContacts] = useState([]);
  
  return (
    <div className="App">
      <UserContext.Provider value={{value, setValue, contacts, setContacts }}>
        <Navbar />
        <div className="content">
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/PersonList" element={<PersonList />} />
            <Route path="/Components/PersonDetails/:id/*" element={<PersonDetails />} />
            <Route path="/LoginForm" element={<LoginForm />} />
          </Routes>
        </div>
      </UserContext.Provider>
    </div>
  );
}

export default App;
  1. 修改PersonList组件,从上下文获取状态,移除内部状态:
import { useContext } from "react";
import UserForm from "./UserForm";
import UserList from "./UserList";
import { UserContext } from "./UserContext";

const PersonList = () => {
  const { contacts, setContacts } = useContext(UserContext);

  const addContact = (contact) => {
    setContacts([...contacts, contact]);
  };

  return (
    <div className="personlist">
      <UserForm addContact={addContact} />
      <UserList contacts={contacts} />
    </div>
  );
}
 
export default PersonList;
  1. 额外优化:避免UserList中每次渲染生成新key
    修改addContact函数,给每个联系人添加唯一id:
const addContact = (contact) => {
  setContacts([...contacts, { ...contact, id: uuid() }]);
};

然后在UserList中使用contact.id作为key:

<tr key={contact.id}>

完成以上修改后,联系人数据会存储在全局上下文中,路由切换时不会丢失,整个浏览过程中数据都会保留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 19:01:02