React JS page keeps refreshing when using the back button
Answer a question
I have 2 React JS pages (A & B), when I go from A->B and back to A, page A is refreshed every time. I was under the impression that page is not destroyed. All related questions on StackOverflow seems to be about the opposite problem.
The reason the page refreshes is because useEffect() is called when the back button is pressed despite using useState() to prevent this. I even tried replacing 'refresh' with a 'props.id' parameter (that never changes). See code below:
Here's my code to page 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>
</>
);
}
I'm using react-router-dom: "^5.1.2", and import { BrowserRouter as Router } from "react-router-dom"; in App.js and specified:
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route exact path="/test">
<Test id="1"/>
</Route>
<Route exact path="/test2">
<Test2 />
</Route>
.....
Does anyone know how to prevent useEffect() from being triggered when returning to page? The actual page A fetches using a REST call and display a long list of items and I do not want the page to refresh every time the user load page B to view item and then returns to the page.
Answers
You need to add a condition to useEffect. If you only want to setRefresh to true if its false, then do something like:
useEffect(() => {
if(!refresh) setRefresh(true)
}, [refresh])
Since you are starting with const [refresh, setRefresh] = useState(false) and are not changing refresh anywhere else in the component, this will run once everytime the component loads (not renders).
If you want to run this once in the lifetime of the app and not the component, you need to persist the information outside the component, by either lifting the state up to a parent component and persisting the information is something like localstorage/sessionstorage.
You could then extract this information whenever your component loads and set the refresh state variable accordingly.
Let's say you just want to setRefresh to true once. Add this useEffect:
useEffect(() => {
let persistedRefresh
try {
persistedRefresh = !!JSON.parse(window.localstorage.getItem('THE_KEY_TO_REFRESH_VALUE'))
} catch(error) {
persistedRefresh = false
}
setRefresh(persistedRefresh)
}, [])
This useEffect will run whenever the component loads, and update the state variable, triggering the previous useEffect.
We also need to modify the previous useEffect:
useEffect(() => {
if(!refresh) {
setRefresh(true)
window.localstorage.setItem('THE_KEY_TO_REFRESH_VALUE', JSON.stringify(true))
}
}, [refresh])
In this useEffect we are updating the persisted value so that whenever the component loads,
- it will check the persisted value,
- refresh if needed, and
- update the persisted value for the next loads.
This is how you do it without any extra dependencies.
更多推荐
所有评论(0)