使用后退按钮时React JS页面不断刷新

jve*_*nce 9 reactjs react-router-dom

我有 2 个 React JS 页面(A 和 B),当我从 A->B 返回 A 时,页面 A 每次都会刷新。我的印象是页面没有被破坏。StackOverflow 上的所有相关问题似乎都是关于相反的问题。

页面刷新的原因是按下后退按钮时会调用 useEffect(),尽管使用 useState() 来防止这种情况发生。我什至尝试用“props.id”参数替换“refresh”(永远不会改变)。参见下面的代码:

这是我的页面 A 的代码:

import { useHistory, useParams } from "react-router-dom";
import React, { useState, useEffect, useRef } from "react";
import { Link } from "react-router-dom";

export default function Test(props) {
    const [refresh, setRefresh] = useState(false);
    
    useEffect(() => {
        console.log("useEffect called: "+refresh);
        setRefresh(true);
    },[refresh]);

    return (
        <>
            Hello from Test
            <Link to="/test2">Test me</Link>
        </>
    );
}
Run Code Online (Sandbox Code Playgroud)

我正在使用react-router-dom:“^ 5.1.2”,并从“react-router-dom”导入{BrowserRouter as Router};在 App.js 中并指定:

  <Switch>
      <Route exact path="/">
        <Home />
      </Route>
          <Route exact path="/test">
        <Test id="1"/>
      </Route>
      <Route exact path="/test2">
        <Test2 />
      </Route>
      .....
Run Code Online (Sandbox Code Playgroud)

有谁知道如何防止返回页面时触发 useEffect() ?实际的页面 A 使用 REST 调用获取并显示一长串项目,我不希望每次用户加载页面 B 以查看项目然后返回到该页面时页面都会刷新。

Aks*_*hay 3

您需要为 useEffect 添加一个条件。如果您只想将 setRefresh 设置为 true(如果为 false),请执行以下操作:

useEffect(() => {
  if(!refresh) setRefresh(true)
}, [refresh])
Run Code Online (Sandbox Code Playgroud)

由于您从组件中的其他任何地方开始const [refresh, setRefresh] = useState(false)并且没有更改刷新,因此每次组件加载(而不是渲染)时都会运行一次。

如果您想在应用程序而不是组件的生命周期中运行一次,则需要将信息保留在组件外部,方法是将状态提升到父组件并保留信息(例如 / localstoragesessionstorage

然后,您可以在组件加载时提取此信息并refresh相应地设置状态变量。

假设您只想将 setRefresh 设置为 true 一次。添加这个useEffect:

useEffect(() => {
  let persistedRefresh
  try {
    persistedRefresh = !!JSON.parse(window.localstorage.getItem('THE_KEY_TO_REFRESH_VALUE'))
  } catch(error) {
    persistedRefresh = false  
  }
  setRefresh(persistedRefresh)
}, [])
Run Code Online (Sandbox Code Playgroud)

这个 useEffect 将在组件加载时运行,并更新状态变量,触发之前的 useEffect。

我们还需要修改之前的useEffect:

useEffect(() => {
  if(!refresh) { 
    setRefresh(true)
    window.localstorage.setItem('THE_KEY_TO_REFRESH_VALUE', JSON.stringify(true))
  }
}, [refresh])
Run Code Online (Sandbox Code Playgroud)

在此,useEffect我们将更新持久值,以便每当组件加载时,

  • 它将检查持久值,
  • 如果需要刷新,并且
  • 更新下一次加载的持久值。

这就是您在没有任何额外依赖的情况下执行此操作的方法。