javascript 如何在React JS中的其他组件中单击返回时保持当前页码处于活动状态

p8ekf7hl  于 2023-06-04  发布在  Java
关注(0)|答案(2)|浏览(191)

如何在React JS中的其他组件中单击返回时保持当前页码处于活动状态。我有三个组件,第一个是设计组件,第二个是分页组件,第三个是项目细节组件。当我点击来自API的数据时,它使用ID并将我带到该特定ID的ItemDetails组件。在ItemDetails组件中,我创建了一个“返回”按钮。我想回到我点击ID的当前页面,但当我点击返回按钮时,它会将我带到第一页。
这里是我的设计组件,我想使用localStorage概念,但如何使用它?我不知道。

// /* 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([]);
  const [currentPage, setCurrentPage] = useState(1);

useEffect(() => {
  const data = window.localStorage.getItem('pnum');
  console.log(`data is: ${data}`)
  if(data !== null) setCurrentPage(JSON.parse(data))
},[])

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>{item.name}</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>
    </>
  );
}

我的itemDetails组件是:

import { useParams } from 'react-router-dom';
import { Link } from 'react-router-dom';

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

  return (
    <div>
      <h2>Item Details</h2>
      <p>{`${id}:I am stuck there.`}</p>
      <Link  to={`/`} style={{ textDecoration: 'none' }}>Go Back</Link>

    </div>
  );
};

export default ItemDetails;
myzjeezk

myzjeezk1#

如果你能提供这个问题的一些最小复制并链接它,可能更容易给予一个有意义的答案,但我们可以尝试一下。
关于如何构建代码来实现这一点,有许多设计决策,这取决于您和您的需求选择什么。现在你的本地存储解决方案是好的,但除非有一些其他的原因,坚持在那里,我个人不会去。如果合适的话,你可以把它保存在树中更高的位置,或者作为url参数,但是我会在后面给予更多的细节。
说实话,我不太确定,没有访问的代码,为什么效果持久的页码不工作。如果我没记错的话,在react中,钩子应该按照声明的顺序运行,我不确定这是一个保证。但即使它是我认为这不是最坚固的设计。
这里有一些替代方案,我不会完全深入,因为有很多可能的变化和大量的文档,所以我只会简要地解释可能的方法,如果你想在一个特定的细节,我可以编辑。

状态您可以将页面保持为状态,只要该状态对于您希望其持久化的所有路由都是通用的。这意味着详细信息页面应该呈现为Design组件的子组件。最极端的例子是将页码存储为应用状态,在此上下文中,react router意味着在树中定义路由或更高路由的组件上。然后它可以与上下文一起暴露,甚至作为 prop 传递,尽管这不是很实用。上下文似乎也不太实际。因此,理想情况下,您应该将其设置为将详细信息页面呈现为Design的后代。有很多方法,它可以是一个对话框/模态,它可以是一些嵌套的路由与出口,为React路由器,你可以查找许多方法。
URL param您也可以将页码设置为可选的url参数,以类似于本地存储的方式更新,然后当您返回时,它将是同一页面,并且您可以更新链接以使用历史记录或类似内容,您甚至可以查看历史记录中的上一个条目并将其显式设置为href。这也具有可以共享页面等的优点。如果有人共享链接,则他们将转到相同的分页,这对于用户来说是方便的。

总而言之,我认为这两种方法都不错,你甚至可以将它们结合起来。我认为如果你研究路由之间的共享状态和url参数,你将在一个很好的位置,你试图实现。

cdmah0mi

cdmah0mi2#

在将初始值设置为状态时,从本地存储中设置值。

const pnum = window.localStorage.getItem('pnum', JSON.stringify(currentPage));
const [currentPage, setCurrentPage] = useState(pnum ?? 1);

相关问题