admin管理员组文章数量:1355014
I’m working on a React application using react-router-dom (version 6.26.1) and encountering an unexpected re-rendering issue. I have a Counter component that updates its state every second to display a timer, and a navigation bar with Link components. The Counter and the nav (containing the Link components) are siblings under BrowserRouter. When the Counter updates its state, the Link components re-render, even though there’s no direct dependency between them (e.g., no shared state, props, or routing hooks in Counter). I’m trying to understand why this is happening.
Code Setup Here’s a simplified version of my application:
// App.js
import { useEffect } from "react";
import { Link, BrowserRouter } from "react-router-dom";
import Counter from "./components/Counter";
const App = () => {
useEffect(() => {
console.log("App rendered");
}, []);
return (
<div className="App">
<BrowserRouter>
<nav>
<ul>
<li>
<Link to="/route_one">Route One</Link>
</li>
<li>
<Link to="/route_one">Route One</Link>
</li>
</ul>
</nav>
<Counter />
</BrowserRouter>
</div>
);
};
export default App;
// ======
// Counter.js
import React, { useEffect, useState } from "react";
const Timer = (props) => {
const { isPaused } = props;
const [seconds, setSeconds] = useState(0);
useEffect(() => {
if (isPaused) {
return;
}
const interval = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);
console.log("Effect has run");
return () => {
clearInterval(interval);
console.log("Timer cleaned up");
};
}, [isPaused]);
return <p>Seconds: {seconds}</p>;
};
const Counter = function () {
const [showTimer, setShowTimer] = useState(true);
const [isPaused, setIsPaused] = useState(false);
const handleTogglePlay = () => {
setIsPaused((prev) => !prev);
};
return (
<div>
{showTimer && <Timer isPaused={isPaused} />}
<button onClick={() => setShowTimer(!showTimer)}>
{showTimer ? "Hide Timer" : "Show Timer"}
</button>
<button onClick={handleTogglePlay}>
{isPaused ? "Play" : "Pause"}
</button>
</div>
);
};
export default Counter;
What I Expect
The Timer component updates its seconds state every second, causing itself to re-render. Since Timer’s state is local and doesn’t affect Counter’s props or state, Counter shouldn’t re-render unless showTimer or isPaused changes. The nav and its Link components, which are siblings of Counter under BrowserRouter, should not re-render because:
- There’s no shared state or props between Counter and nav.
- Timer doesn’t use any react-router-dom hooks (e.g., useLocation), so it shouldn’t interact with the routing context.
- The location isn’t changing (I’m staying on the same route).
What I Observe
Using React DevTools, I see that the Link components re-render every second, matching the timer’s update frequency.
The React Profiler shows that Link re-renders because its parent (Location_Provider, an internal component of react-router-dom) re-renders. Here’s a screenshot of the profiler:
Additionally, when I enable "Highlight updates when components render" in React DevTools, I see highlights on the Link components and their parents every second as the timer updates.
My Confusion
I don’t understand why Location_Provider (or another parent component in react-router) re-renders when Timer updates its state. There’s no direct dependency between Timer and the routing context, and the location isn’t changing. I expected that a child component’s state change (Timer) would only cause itself to re-render, not its siblings (Link) or parents (Location_Provider).
What I’ve Tried
I confirmed that App only renders once (via the console.log in useEffect), so the children prop passed to BrowserRouter is stable. I checked that Timer doesn’t use any routing hooks, so it shouldn’t be subscribing to the routing context.
Questions
Why does Location_Provider re-render when Timer updates its state, even though there’s no location change or direct dependency?
Is this a known behavior in react-router(v7.4.1), where internal components like Location_Provider re-render during reconciliation, even without context changes?
How can I prevent Link from re-rendering in this scenario, or is this expected behavior that I should accept?
I’m not concerned about performance at this stage (the re-renders are fast), but I want to understand why this is happening to improve my understanding of React and react-router-dom. Any insights would be appreciated!
版权声明:本文标题:reactjs - Why does Link re-render when a sibling component updates its state in React Router? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744001107a2573873.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论