useNavigation 更改 URL,但不渲染或显示组件

问题描述 投票:0回答:1

考虑以下代码:

https://codesandbox.io/p/sandbox/hardcore-lake-mptzw3

App.jsx:

import ContextProvider from "./provider/contextProvider";
import Routes from "./routes";
function App() {
  console.log("In App");

  return (
    <ContextProvider>
      <Routes />
    </ContextProvider>
  );
}

export default App;

路由.jsx:

import { RouterProvider, createBrowserRouter } from "react-router-dom";
import { provideContext } from "./provider/contextProvider";
import Component1 from "./pages/Component1";
import Component2 from "./pages/Component2";
const Routes = () => {
  const { token } = provideContext();

  const router = createBrowserRouter([
    {
      path: "/Component2",
      element: <Component2 />,
    },
    {
      path: "/Component1",
      element: <Component1 />,
    },
  ]);


  return <RouterProvider router={router} />;
};

export default Routes;

pages/Component1.jsx:

const Component1 = () => {
  console.log("In Component1");

  return <div>Component1</div>;
};

export default Component1;

pages/Component2.jsx:

import { useNavigate } from "react-router-dom";
import { provideContext } from "../provider/contextProvider";

const Component2 = () => {
  const navigate = useNavigate();
  const { setToken } = provideContext();
  console.log("In Component2");
  const onClick = () => {
    setToken("Token");
    setTimeout(() => {
      navigate("/Component1");
    });
  };

  return (
    <>
      <button onClick={onClick}>Click me</button>
    </>
  );
};

export default Component2;

提供者/ContextProvider.jsx:

import { createContext, useContext, useState } from "react";

const Context = createContext();

const ContextProvider = ({ children }) => {
  const [token, setToken] = useState("Initial");

  return (
    <Context.Provider value={{ token, setToken }}>{children}</Context.Provider>
  );
};

export const provideContext = () => {
  return useContext(Context);
};

export default ContextProvider;

点击

Component2
中的按钮时,URL发生变化,但UI仍然显示
Component2.
Component 1
甚至没有渲染一次。

有趣的是,如果我删除

setTimeout()
函数中的
Component2.jsx
或删除
const { token } = provideContext();
中的
Routes.jsx
,问题就会消失。不知道发生了什么。

javascript reactjs react-router-dom
1个回答
0
投票

问题是在 ReactTree 内声明路由器。

要么移动声明路由器外部ReactTree:

import { RouterProvider, createBrowserRouter } from "react-router-dom";
import { provideContext } from "./provider/ContextProvider";
import Component1 from "./pages/Component1";
import Component2 from "./pages/Component2";

const router = createBrowserRouter([
  {
    path: "/Component2",
    element: <Component2 />,
  },
  {
    path: "/Component1",
    element: <Component1 />,
  },
]);

const Routes = () => {
  const { token } = provideContext();

  return <RouterProvider router={router} />;
};

export default Routes;

或者记忆路由器,这样当上下文状态更新时,它就不会在每个渲染周期中重新声明:

import { useMemo } from "react";
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import { provideContext } from "./provider/ContextProvider";
import Component1 from "./pages/Component1";
import Component2 from "./pages/Component2";

const Routes = () => {
  const { token } = provideContext();

  const router = useMemo(() =>
    createBrowserRouter([
      {
        path: "/Component2",
        element: <Component2 />,
      },
      {
        path: "/Component1",
        element: <Component1 />,
      },
    ]), [] // <-- add any required dependencies here
  );

  return <RouterProvider router={router} />;
};

export default Routes;

您确实不需要使用

setTimeout
来发出导航操作。删除
setTimeout
中的
Component2

import { useNavigate } from "react-router-dom";
import { provideContext } from "../provider/ContextProvider";

const Component2 = () => {
  const navigate = useNavigate();
  const { setToken } = provideContext();

  const onClick = () => {
    setToken("Token");
    navigate("/Component1");
  };

  return (
    <>
      <button onClick={onClick}>Click me</button>
    </>
  );
};

export default Component2;
© www.soinside.com 2019 - 2024. All rights reserved.