![](/img/trans.png)
[英]React Router v4 everything in the Router component re-renders on every route change
[英]React Router V6 Re-renders on Route Change
當我在路由之間來回導航時,React Router 會重新渲染記憶的路由,導致useEffect(() => [])
重新運行並重新獲取數據。 我想防止這種情況發生,而是保留現有路線但隱藏在dom中。 不過,我正在為“如何”而苦苦掙扎。
以下是該問題的示例代碼:
import React, { useEffect } from "react";
import { BrowserRouter as Router, Route, Routes, useNavigate } from "react-router-dom";
export default function App() {
return (
<Router>
<Routes>
<Route path={"/"} element={<MemoizedRouteA />} />
<Route path={"/b"} element={<MemoizedRouteB />} />
</Routes>
</Router>
);
}
function RouteA() {
const navigate = useNavigate()
useEffect(() => {
alert("Render Router A");
}, []);
return (
<button onClick={() => { navigate('/b') }}>Go to B</button>
);
};
const MemoizedRouteA = React.memo(RouteA)
function RouteB() {
const navigate = useNavigate()
useEffect(() => {
alert("Render Router B");
}, []);
return (
<button onClick={() => { navigate('/') }}>Go to A</button>
);
}
const MemoizedRouteB = React.memo(RouteB)
沙盒: https://codesandbox.io/s/wonderful-hertz-w9qoip?file=/src/App.js
使用上面的代碼,您將看到每當您點擊按鈕或使用瀏覽器后退按鈕時都會調用“警報”代碼。
多年來,React Router 發生了如此多的變化,我正在努力尋找解決方案。
當我在路由之間來回導航時,React Router 會重新渲染記憶的路由,導致
useEffect(() => [])
重新運行並重新獲取數據。 我想防止這種情況發生,而是保留現有路線但隱藏在dom中。 不過,我正在為“如何”而苦苦掙扎。
長話短說,你不能。 React 組件出於以下三個原因之一重新渲染:
使用memo
HOC 的原因在這里不起作用,因為Routes
組件一次只匹配和呈現單個Route
組件的element
prop。 從"/"
導航到"/b"
必然會卸載MemoizedRouteA
並安裝MemoizedRouteB
,反之亦然。 這正是 RRD 的工作方式。 這就是 React 組件生命周期的工作方式。 在安裝/卸載組件時,記住組件 output 無法執行任何操作。
如果您真正想要最小化/減少/避免的是組件安裝時重復的異步調用和數據獲取/重新獲取,那么我在這里建議的是應用Lifting State Up模式並將 state 和useEffect
調用移動到父級/祖先。
這是一個使用Outlet
組件及其提供的上下文的簡單示例,但 state 可以通過任何其他方式提供,例如常規 React 上下文或 Redux。
import React, { useEffect, useState } from "react";
import {
BrowserRouter as Router,
Route,
Routes,
Outlet,
useNavigate,
useOutletContext
} from "react-router-dom";
export default function App() {
const [users, setUsers] = useState(0);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then(setUsers);
}, []);
return (
<Router>
<Routes>
<Route element={<Outlet context={{ users }} />}>
<Route path={"/"} element={<RouteA />} />
<Route path={"/b"} element={<RouteB />} />
</Route>
</Routes>
</Router>
);
}
function RouteA() {
const navigate = useNavigate();
return (
<div>
<button onClick={() => navigate("/b")}>Go to B</button>
</div>
);
}
function RouteB() {
const navigate = useNavigate();
const { users } = useOutletContext();
return (
<div>
<button onClick={() => navigate("/")}>Go to A</button>
<ul>
{users.map((user) => (
<li key={user.id}>
{user.name} : {user.email}
</li>
))}
</ul>
</div>
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.