suchen

Heim  >  Fragen und Antworten  >  Hauptteil

REAGIEREN – Vermeiden Sie das erneute Rendern der Seite auf der Post-Browser-Schaltfläche

Ich habe eine Katalogseite, auf der viele Produkte angezeigt werden. Sobald der Benutzer auf eines der Produkte klickt, die er unten auswählen kann, beispielsweise Produktnummer 1000, geht er zu einer anderen Seite, überprüft den Inhalt usw. … und wenn er verwendet die Schaltfläche „Zurück“ Wenn der Browser zur Katalogseite zurückkehrt, wird alles erneut gerendert, was zwar Sinn macht, aber viel Zeit in Anspruch nimmt, um die Bildlaufleiste auf das zuvor ausgewählte Produkt zu positionieren.

Wenn der Benutzer oben auf der Seite ein bestimmtes Produkt (z. B. Produktnummer 4) auswählt, funktioniert alles gut, aber wenn er nach unten geht, beginnt das Szenario.

Gibt es eine Möglichkeit, diese Verzeichnisseite in REACT zwischenzuspeichern? Um die Zeit zu sparen, die zum Rendern benötigt wird?

Paginierung unten auf der Seite mit dem Inhaltsverzeichnis löst dieses Problem, aber ich habe eine Schaltfläche „Mehr laden“. Ich habe versucht, React.memo zu verwenden, aber es funktioniert nur, wenn ich eine Aktion auf der aktuellen Seite ausführe, nicht, wenn ich über die Schaltfläche „Zurück“ auf der Seite lande.

Ich verwende React Router v5. Ich könnte hier einen Codepen mit dem Code hinzufügen, aber zuerst würde ich gerne wissen, ob dies möglich ist, damit ich eine Richtung vorgeben kann. Ich habe Seiten gesehen, die nach dem Zurückgehen mit der Zurück-Schaltfläche sogar alles rendern müssen, wie eine statische Seite aussehen und beim Scrollen nicht einmal dorthin verschoben werden, wo das letzte Produkt ausgewählt wurde. Gibt es Licht in der Dunkelheit?

Das ist mein Beispiel.

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;

P粉733166744P粉733166744237 Tage vor444

Antworte allen(1)Ich werde antworten

  • P粉762447363

    P粉7624473632024-03-28 10:38:14

    问题

    因此,应用程序中存在一些对您不利的因素。

    1. 数据被获取并存储在正在导航到的组件的本地状态中。一旦应用导航到另一条路线,数据就会丢失,并在返回时重新获取。
    2. 大量数据需要渲染。

    可能的建议解决方案

    为了解决状态持久性问题,这里的解决方案是将状态提升到共同祖先的模式,使其比正在渲染的路由组件持续更长时间。在父 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 (
        
          {children}
        
      );
    };
    export default function App() {
      return (
        
    home
    page 1
    page 2
    // <-- card data provided to all routes
    ); }

    为了解决需要渲染的数据量问题,您可以转向虚拟化或窗口化。 react-window 就是处理这个问题的一个。其作用是,它不会将整个数据数组(可能有数千个元素)渲染到 DOM,而是仅渲染适合屏幕的内容以及前后的一些“过度扫描”。

    示例:

    import { FixedSizeList as List } from "react-window";
    import AutoSizer from "react-virtualized-auto-sizer";
    
    const Page1 = () => {
      const { cards } = useCardData();
    
      return (
        
    {({ height, width }) => ( {({ index, style }) => (
    )}
    )}
    ); };

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

    const CardDataContext = createContext({
      cards: [],
      scrollIndex: null,
      setScrollIndex: () => {}
    });
    
    ...
    
    const CardDataProvider = ({ children }) => {
      ...
      const [scrollIndex, setScrollIndex] = useState(null);
    
      ...
    
      return (
        
          {children}
        
      );
    };
    const Page1 = () => {
      const { cards, scrollIndex, setScrollIndex } = useCardData();
    
      const listRef = useRef();
    
      useEffect(() => {
        if (scrollIndex) {
          setTimeout(() => {
            listRef.current.scrollToItem(scrollIndex, "center");
          });
        }
      }, [scrollIndex]);
    
      return (
        
    {({ height, width }) => ( {({ index, style }) => (
    setScrollIndex(index)}>
    )}
    )}
    ); };

    演示

    Antwort
    0
  • StornierenAntwort