javascript REACT -避免在后退浏览器按钮上重新呈现页面

t1rydlwq  于 2023-02-28  发布在  Java
关注(0)|答案(2)|浏览(172)

我有一个目录页面,显示了很多产品,一旦用户单击其中一个产品,他可能选择从底部,让说产品编号1000,他去到另一个页面,检查东西等...当他返回到目录页面使用后退按钮浏览器一切都呈现了一遍,这是有道理的,但是将滚动条定位到之前选择的产品需要大量的时间。
当用户在页面顶部选择某个产品(比如产品编号4)时,一切都很顺利,但当他转到底部时,场景就开始了。
是否有任何方法可以在REACT中缓存此目录页?以避免呈现所需的时间?
在我的目录页面底部分页解决了这个问题,但我有一个加载更多按钮。我尝试使用React. memo,但它只在我在当前页面上做事情时工作,而不是当我使用后退按钮进入页面时。
我正在使用react router v5。我可以在这里添加一些codepen代码,但首先我想知道这是否是可能的,以便采取一些方向。我看到的网页,甚至需要渲染一切,一旦你使用返回按钮返回,看起来像静态页面和滚动甚至没有移动到最后选择的产品的位置。任何光在黑暗中?
这是我的例子。

    • 应用程序jsx**
import React, { StrictMode } from 'react';
import { BrowserRouter, Switch, Route, Link } from 'react-router-dom'
import './App.css';
import Home from './Home';
import Page1 from './Page1';
import Page2 from './Page2';

function App() {
  return (
    <StrictMode>
    <BrowserRouter>
      <div className="App">
        <header className="App-header">
          <Link to='/'>home</Link><br />
          <Link to='/page1'>page 1</Link><br />
          <Link to='/page2'>page 2</Link><br />
        </header>
        <Switch>
          <Route path='/page1'>
            <Page1 />
          </Route>
          <Route path='/page2'>
            <Page2 />
          </Route>
          <Route path='/'>
            <Home />
          </Route>
        </Switch>
      </div>
    </BrowserRouter>
    </StrictMode>
  );
}

export default App;
    • 主页. jsx**
import React from 'react';

const Home = () => <h1>This is the home</h1>

export default Home;
    • 第一页. jsx**
import React, { useEffect, useState } from 'react';
import Card from './Card';

const Page1 = () => {

  const [cards, setCards] = useState([]);

  const fetchData = () => {
    fetch('https://jsonplaceholder.typicode.com/photos')
      .then((response) => response.json())
      .then((json) => setCards(json))
      .then(() => scrollToElement());
  }

  const scrollToElement = () => {
    const id = localStorage.getItem('idRef');
    if (id) {
      var access = document.getElementById(id);
      access.scrollIntoView();
    }
  } 

  useEffect(() => {
    fetchData()
  }, [])

  return (
    <div className="grid">
      {cards.map((item) => <Card item={item} key={item.id}/>)}
    </div>
  )
}

export default Page1;
    • 第二页. jsx**
import React from 'react';

const Page2 = () => <h1>Product selected... now click back browser button</h1>

export default Page2;
hc8w905p

hc8w905p1#

也许您可以尝试使用window.history沿着pushState()方法将目录页面的滚动存储在浏览历史中,看看是否有效。

z4iuyo4d

z4iuyo4d2#

问题

所以在应用程序中有几件事对你不利。
1.数据被提取并存储在导航到的组件的本地状态中。一旦应用导航到另一个路径,数据就会丢失,并在导航回来时重新提取。
1.有"很多"数据要呈现。

可能的建议解决方案

要解决状态持久性的问题,这里的解决方案是将提升状态的模式应用到公共祖先,使其持久性长于正在呈现的路由组件。在父App组件中或自定义React Context提供程序组件就足够了。
示例:

import { createContext, useContext, useEffect, useState } from "react";

const CardDataContext = createContext({
  cards: [],
});

const useCardData = () => useContext(CardDataContext);

const CardDataProvider = ({ children }) => {
  const [cards, setCards] = useState([]);

  const fetchData = () => {
    fetch("https://jsonplaceholder.typicode.com/photos")
      .then((response) => response.json())
      .then((json) => setCards(json));
  };

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

  return (
    <CardDataContext.Provider value={{ cards }}>
      {children}
    </CardDataContext.Provider>
  );
};
export default function App() {
  return (
    <div className="App">
      <header className="App-header">
        <Link to="/">home</Link>
        <br />
        <Link to="/page1">page 1</Link>
        <br />
        <Link to="/page2">page 2</Link>
        <br />
      </header>
      <CardDataProvider> // <-- card data provided to all routes
        <Switch>
          <Route path="/page1" component={Page1} />
          <Route path="/page2" component={Page2} />
          <Route path="/" component={Home} />
        </Switch>
      </CardDataProvider>
    </div>
  );
}

为了解决需要渲染的数据量问题,你可以求助于虚拟化或窗口化。react-window是一个处理这个问题的工具。它所做的是,它不把 * 整个 * 数据数组(可能有数千个元素)渲染到DOM,而是只渲染适合屏幕的内容,再加上前后的一点"过扫描"。
示例:

import { FixedSizeList as List } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";

const Page1 = () => {
  const { cards } = useCardData();

  return (
    <div className="grid">
      <AutoSizer>
        {({ height, width }) => (
          <List
            height={height}
            itemCount={cards.length}
            itemSize={150}
            width={width}
          >
            {({ index, style }) => (
              <div style={style}>
                <Card item={cards[index]} />
              </div>
            )}
          </List>
        )}
      </AutoSizer>
    </div>
  );
};

要解决的最后一个问题是滚动恢复到特定元素。react-window具有滚动到特定索引的能力。我们可以更新CardDataContext以保持某些滚动状态,并更新Page1组件以设置和恢复位置。
一个三个三个一个

演示

相关问题