如何在路由器改变时重新渲染和运行useEffect (React js)



我有一个ChartPage函数,在三个不同的路由器中被调用了三次,在这个ChartPage函数中,我使用了"useEffect"根据所选路线更新一些变量。但由于某种原因,它只触发了一次,当我要使用相同的ChartPage函数的不同路线时,"useEffect"不会再次被触发,即使路由发生变化,数据仍然与第一次被触发的路由相同。
有人能帮我解决这个问题吗,我试着解决这个问题几个小时

基本上我想在点击某个按钮时触发useEffect

app.js:

import React from "react";
import Navbar from "./components/Navbar";
import "./App.css";
import Home from "./components/pages/Home";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import ShowStocks from "./components/pages/ShowStocks";
import ChartPage from "./components/pages/ChartPage";
function App() {
return (
<>
<Router>
<Navbar />
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/show-stocks" element={<ShowStocks />} />
<Route
path="show-stocks/bitcoin"
element={<ChartPage type={"BTC"} />}
/>
<Route
path="show-stocks/ethereum"
element={<ChartPage type={"ETH"} />}
/>
<Route
path="show-stocks/cardano"
element={<ChartPage type={"ADA"} />}
/>
</Routes>
</Router>
</>
);
}
export default App;

正如你所看到的,我在三个不同的路由中使用ChartPage,但不是使用相同的数据
ChartPage.js:

import React, { Component, useState, useEffect } from "react";
import "../../App.css";
import Chart from "../Chart";
import { Button } from "../Button.js";
import "./ChartPage.css";
import axios from "axios";
function getCoin(type) {
console.log("requesting");
var path = `/show-stocks/${type}`;
return axios.get(path).then((response) => {
return response.data;
});
}
export default function ChartPage({ type }) {
const [values, setValues] = useState(null);
// type is changing correctly and the function did get called with a different type
// but useEffect doesn't run on the second time
// so getCoin does not get triggerd and the data stays the same 
useEffect(() => {
getCoin(type)
.then((response) => {
setValues(response);
})
.catch((error) => {
console.log(error);
});
}, []);
return (
<>
<div className="chart-page-container">
<h1>{type} Price Market Value</h1>
<div className="chart-container">
{null !== values ? (
<Chart data={[values, type]} />
) : (
<p>Loading...</p>
)}
</div>
<div className="chart-page-btns">
<Button
link="/show-stocks/bitcoin"
className="btns"
buttonStyle="btn--outline2"
buttonSize="btn--large2"
>
Bitcoin
</Button>
<Button
link="/show-stocks/ethereum"
className="btns"
buttonStyle="btn--outline2"
buttonSize="btn--large2"
>
Ethereum
</Button>
<Button
link="/show-stocks/cardano"
className="btns"
buttonStyle="btn--outline2"
buttonSize="btn--large2"
>
Cardano
</Button>
</div>
</div>
</>
);
}

你可以看到按钮改变路由和类型根据路由发送的参数更新,但是useEffect没有再次调用。

type添加到useEffect的依赖项数组中:

useEffect(() => {
getCoin(type)
.then((response) => {
setValues(response);
})
.catch((error) => {
console.log(error);
});
}, [type]); // <= HERE

请记住,这段代码有一些问题,因为如果发生类似这样的事情,您可能最终会看到与URL中的类型不匹配的数据:

  • 导航到/type-a,getCoin('type-a')被调用。
  • 你导航到/type-b,getCoin('type-b')被调用。
  • type-b完成加载,因此执行then回调。
  • type-a完成装载时,所以它then回调执行。
  • 你现在在/type-b,但看到type-a的数据。

正确的方法是这样做:

useEffect(() => {
let shouldUpdate = true;
getCoin(type)
.then((response) => {
if (shouldUpdate) setValues(response);
})
.catch((error) => {
console.log(error);
});
// This cleanup function will be called if the `useEffect`'s
// dependencies change, so if you run it twice in a row for
// different types, when the result of the first one arrives,
// it will be discarded:
return () => {
shouldUpdate = false;
};
}, [type]);