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

React中点击返回按钮时保留当前页码的实现咨询

解决返回详情页后回到原列表页码的问题

问题分析

当前点击详情页的"Go Back"按钮回到列表页时,会默认回到第一页。我们可以通过localStorage保存用户点击进入详情页时的当前页码,在列表页重新加载时恢复该页码,实现返回原页面的效果。

修改方案

1. 优化Design组件的页码存储与初始化逻辑

将当前页码的初始化逻辑直接放在useState的初始值中,避免异步更新导致的初始显示第一页问题,同时保留页码变化时自动存储的逻辑:

// /* eslint-disable react/prop-types */ // TODO: upgrade to latest eslint tooling
import "../src/App.css";
import axios from "axios";
import { useEffect, useState, useMemo } from "react";
import Pagination from "./Pagination";
import { Link } from "react-router-dom";

let PageSize = 2;

export default function Design() {
  const [search, setSearchTerm] = useState("all");
  const [records, setRecords] = useState([]);
  const [suggestions, setSuggestions] = useState([]);
  // 直接从localStorage读取初始页码,没有则设为1
  const [currentPage, setCurrentPage] = useState(() => {
    const savedPage = window.localStorage.getItem('pnum');
    return savedPage ? JSON.parse(savedPage) : 1;
  });

  // 页码变化时自动保存到localStorage
  useEffect(() => {
    window.localStorage.setItem('pnum', JSON.stringify(currentPage));
  }, [currentPage])

  const currentTableData = useMemo(() => {
    const firstPageIndex = (currentPage - 1) * PageSize;
    const lastPageIndex = firstPageIndex + PageSize;
    return records.slice(firstPageIndex, lastPageIndex);
  }, [currentPage, records]);

  useEffect(() => {
    searchRecords();
  }, []);

  const searchRecords = async () => {
    try {
      const res = await axios.get(`https://fruityvice.com/api/fruit/${search}`);
      setRecords(search === "all" ? res.data : [res.data]);
    } catch (error) {
      console.error("Error searching record:", error);
      setRecords([]);
    }
  };

  const fetchSuggestions = async (input) => {
    try {
      const res = await axios.get(`https://fruityvice.com/api/fruit/all`);
      const fruits = res.data.map((fruit) => fruit.name);
      const filteredSuggestions = fruits.filter((fruit) =>
        fruit.toLowerCase().includes(input.toLowerCase())
      );
      setSuggestions(filteredSuggestions);
    } catch (error) {
      console.error("Error fetching suggestions:", error);
      setSuggestions([]);
    }
  };

  const handleInputChange = (e) => {
    const inputValue = e.target.value;
    setSearchTerm(inputValue);
    fetchSuggestions(inputValue);
  };

  const getTotalNutritions = (item) => {
    return Object.values(item.nutritions).reduce(
      (total, value) => total + Math.trunc(value),
      0
    );
  };

  return (
    <>
      <h1 className="main--heading">Fruit Project</h1>
      <div className="main">
        <input
          className="input"
          onChange={handleInputChange}
          list="suggestions"
          placeholder="Search Fruit"
        />
        <datalist id="suggestions">
          {suggestions.map((fruit, index) => (
            <option key={index} value={fruit} />
          ))}
        </datalist>
        <button className="btn" onClick={searchRecords}>
          Search Fruit
        </button>
      </div>
      <div>
        <table>
          <thead>
            <tr>
              <th>Sr No</th>
              <th>Name</th>
              <th>Family</th>
              <th>Order</th>
              <th>Nutritions</th>
              <th>Genus</th>
            </tr>
          </thead>
          <tbody>
            {Array.isArray(currentTableData) && currentTableData.length > 0 ? (
              currentTableData
                .sort((a, b) => a.id - b.id)
                .map((item) => (
                  <tr key={item.id}>
                    <td>{item.id}</td>
                    <td>
                      <Link to={`/details/${item.id}`}>View Details</Link>
                    </td>
                    <td>{item.family}</td>
                    <td>{item.order}</td>
                    <td>{getTotalNutritions(item)}</td>
                    <td>{item.genus}</td>
                  </tr>
                ))
            ) : (
              <tr>
                <td>No data available</td>
              </tr>
            )}
          </tbody>
        </table>
        <Pagination
          className="pagination-bar"
          currentPage={currentPage}
          totalCount={records.length}
          pageSize={PageSize}
          onPageChange={(page) => setCurrentPage(page)}
        />
      </div>
    </>
  );
}

2. 可选优化ItemDetails组件的返回逻辑

如果希望更符合浏览器的返回行为,可以将Link替换为useNavigate实现返回上一页,这样即使用户从其他页面进入详情页,也能回到正确的上一级页面:

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

const ItemDetails = () => {
  const { id } = useParams();
  const navigate = useNavigate();

  return (
    <div>
      <h2>Item Details</h2>
      <p>{`${id}:I am stuck there.`}</p>
      <button onClick={() => navigate(-1)} style={{ textDecoration: 'none', background: 'none', border: 'none', color: 'blue', cursor: 'pointer' }}>
        Go Back
      </button>
    </div>
  );
};

export default ItemDetails;

原理说明

  • 当用户切换列表页码时,currentPage状态变化,触发useEffect将页码存入localStorage。
  • 列表页初始化时,直接从localStorage读取之前保存的页码作为初始值,确保返回时显示用户之前停留的页面。
  • 可选的navigate(-1)方式利用浏览器历史记录返回,无需依赖localStorage也能回到原页面状态,适合更复杂的路由场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 06:00:06