如何防止组件在路径更改时卸载?

huangapple go评论75阅读模式
英文:

How to prevent components from unmounting when path changes?

问题

有没有办法阻止路由卸载?在我的应用程序中,我需要在切换路由时保留React状态。

在这里,您可以看到,如果我们更改路由,然后主页对应的 route 组件将会 mountunmount。我不想要这个。

CODESANDBOX DEMO

我已经查看过

如何防止React组件卸载?

如何防止React卸载/重新挂载组件?

但对我不起作用。

index.js

import React from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./App";
import First from "./routes/First";
import Second from "./routes/Second";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <BrowserRouter>
    <Routes>
      <Route path="" element={<App />} />
      <Route path="first" element={<First />} />
      <Route path="second" element={<Second />} />
    </Routes>
  </BrowserRouter>
);

App.js

import * as React from "react";
import { Link } from "react-router-dom";

export default function App() {
  return (
    <div>
      <h1>Prevent Routing</h1>
      <nav
        style={{
          borderBottom: "solid 1px",
          paddingBottom: "1rem"
        }}
      >
        <Link to="/first">First</Link> |<Link to="/second">Second</Link>
      </nav>
    </div>
  );
}

First.js

import * as React from "react";
import { useEffect } from "react";
import { Link } from "react-router-dom";

export default function First() {
  useEffect(() => {
    console.log("mounted First");

    return () => console.log("unmounted First");
  }, []);

  return (
    <main style={{ padding: "1rem 0" }}>
      <Link to="/">Home</Link>
      <h2>First</h2>
    </main>
  );
}

Second.js

import * as React from "react";
import { useEffect } from "react";
import { Link } from "react-router-dom";

export default function Second() {
  useEffect(() => {
    console.log("mounted Second");

    return () => console.log("unmounted Second");
  }, []);

  return (
    <main style={{ padding: "1rem 0" }}>
      <Link to="/">Home</Link>
      <h2>Second</h2>
    </main>
  );
}
英文:

Is there a way to stop the route from unmounting? In my app I would need to keep react state between switching the routes.

Here you can see that, if we change route then home respective route component will mount and unmount. I don't want.

CODESANDBOX DEMO

I've looked in

How can I prevent the unmount in React Components?

How can I prevent React from unmounting/remounting a component?

but doesn't work for me.

index.js

import React from &quot;react&quot;;
import { createRoot } from &quot;react-dom/client&quot;;
import { BrowserRouter, Routes, Route } from &quot;react-router-dom&quot;;
import App from &quot;./App&quot;;
import First from &quot;./routes/First&quot;;
import Second from &quot;./routes/Second&quot;;

const rootElement = document.getElementById(&quot;root&quot;);
const root = createRoot(rootElement);

root.render(
  &lt;BrowserRouter&gt;
    &lt;Routes&gt;
      &lt;Route path=&quot;&quot; element={&lt;App /&gt;} /&gt;
      &lt;Route path=&quot;first&quot; element={&lt;First /&gt;} /&gt;
      &lt;Route path=&quot;second&quot; element={&lt;Second /&gt;} /&gt;
    &lt;/Routes&gt;
  &lt;/BrowserRouter&gt;
);

App.js

import * as React from &quot;react&quot;;
import { Link } from &quot;react-router-dom&quot;;

export default function App() {
  return (
    &lt;div&gt;
      &lt;h1&gt;Prevent Routing&lt;/h1&gt;
      &lt;nav
        style={{
          borderBottom: &quot;solid 1px&quot;,
          paddingBottom: &quot;1rem&quot;
        }}
      &gt;
        &lt;Link to=&quot;/first&quot;&gt;First&lt;/Link&gt; |&lt;Link to=&quot;/second&quot;&gt;Second&lt;/Link&gt;
      &lt;/nav&gt;
    &lt;/div&gt;
  );
}

First.js

import * as React from &quot;react&quot;;
import { useEffect } from &quot;react&quot;;
import { Link } from &quot;react-router-dom&quot;;

export default function First() {
  useEffect(() =&gt; {
    console.log(&quot;mounted First&quot;);

    return () =&gt; console.log(&quot;unmounted First&quot;);
  }, []);

  return (
    &lt;main style={{ padding: &quot;1rem 0&quot; }}&gt;
      &lt;Link to=&quot;/&quot;&gt;Home&lt;/Link&gt;
      &lt;h2&gt;First&lt;/h2&gt;
    &lt;/main&gt;
  );
}

Second.js

import * as React from &quot;react&quot;;
import { useEffect } from &quot;react&quot;;
import { Link } from &quot;react-router-dom&quot;;

export default function Second() {
  useEffect(() =&gt; {
    console.log(&quot;mounted Second&quot;);

    return () =&gt; console.log(&quot;unmounted Second&quot;);
  }, []);

  return (
    &lt;main style={{ padding: &quot;1rem 0&quot; }}&gt;
      &lt;Link to=&quot;/&quot;&gt;Home&lt;/Link&gt;
      &lt;h2&gt;Second&lt;/h2&gt;
    &lt;/main&gt;
  );
}

答案1

得分: 1

React Router在组件不匹配path时总是会卸载该组件。

你可以通过将两个组件与双重路由组合来解决这个问题,每个组件可以根据当前的path确定要渲染什么。

因此,主要路由看起来会像这样:

<Route path={[ '/first', '/second' ]}>
    <First {...{}} />
    <Second {...{}} />
</Route>

然后在组件中使用useLocation来切换渲染:

import { useLocation } from "react-router-dom";

function First(props) {

    const location = useLocation();

    if (location.pathname !== '/first') {
        return null
    }
}
英文:

React Router will always unmount the component when it's not matched by a path.


You could fix this by combining both Components with a double route, each component can determine what he will render based on the current path.

So the main routing will look something like:

&lt;Route path={[ &#39;/first&#39;, &#39;/second&#39; ]}&gt;
    &lt;First {...{}} /&gt;
    &lt;Second {...{}} /&gt;
&lt;/Route&gt;

Then use useLocation in the component to toggle the render:

import { useLocation } from &quot;react-router-dom&quot;;

function First(props) {

    const location = useLocation();

    if (location.pathname !== &#39;/first&#39;) {
        return null
    }
}

huangapple
  • 本文由 发表于 2023年1月9日 19:00:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75056324.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定