簡體   English   中英

路由器更改時如何重新渲染和運行useEffect(React js)

[英]How to re-render and run useEffect when router change (React js)

我有一個ChartPage函數,它在三個不同的路由器內被調用了三次,在該ChartPage函數中,我使用的是“useEffect”,它根據所選路由更新一些變量。 但由於某種原因,它只觸發一次,當我要去使用相同ChartPage功能的不同路線時,“useEffect”不會再次觸發,即使路線正在改變,數據仍然與第一條路線相同被觸發了。
有人可以幫助解決這個問題嗎,我試圖解決這個問題幾個小時

基本上我想在單擊其中一個按鈕時觸發“useEffect”

應用程序.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-agetCoin('type-a')
  • 您導航到/type-bgetCoin('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]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM