我有一个显示很多产品的目录页面,一旦用户单击他可能从底部选择的产品之一,比如说产品编号 1000,他就会转到另一个页面,检查内容等...并且当他使用后退按钮浏览器返回目录页面时,所有内容都会再次呈现,这是有道理的,但需要花费大量时间将滚动条定位到先前选择的产品。
当用户在页面顶部选择某个产品(例如产品号 4)时,一切都运行良好,但当他转到底部时,场景就开始了。
有什么办法可以在 REACT 中缓存这个目录页面吗?为了避免渲染所需的时间?
目录页面底部的分页解决了此问题,但我有一个“加载更多”按钮。我尝试使用 React.memo,但它仅在我在当前页面上执行操作时有效,而不是在我使用后退按钮登陆页面时有效。
我正在使用React Router v5。我可以在此处添加一些带有代码的代码笔,但首先我想知道这是否可行,以便采取一些方向。我看到页面甚至需要在使用后退按钮返回后渲染所有内容,看起来像静态页面,并且滚动甚至不会移动到最后选择的产品的位置。黑暗中还有光吗?
这是我的例子。
App.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;
Home.jsx
import React from 'react'; const Home = () => <h1>This is the home</h1> export default Home;
Page1.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;
Page2.jsx
import React from 'react'; const Page2 = () => <h1>Product selected... now click back browser button</h1> export default Page2;
问题
因此,应用程序中存在一些对您不利的因素。
可能的建议解决方案
为了解决状态持久性问题,这里的解决方案是将状态提升到共同祖先的模式,使其比正在渲染的路由组件持续更长时间。在父
App
组件中或自定义 React Context 提供程序组件就足够了。示例:
为了解决需要渲染的数据量问题,您可以转向虚拟化或窗口化。
react-window
就是处理这个问题的一个。其作用是,它不会将整个数据数组(可能有数千个元素)渲染到 DOM,而是仅渲染适合屏幕的内容以及前后的一些“过度扫描”。示例:
最后要解决的一件事是滚动恢复到特定元素。
react-window
能够滚动到特定索引。我们可以更新CardDataContext
以保持某些滚动状态,并更新Page1
组件以设置和恢复位置。演示