最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - Extra Rendering of the Previous Route Component When Navigating with useNavigate in react-router-dom - Stack Overflow

programmeradmin1浏览0评论

I'm using React Router as a...

library

Reproduction

I have two sibling route components: Home and Login.

When executing the following navigation code in the Home component:

const navigate = useNavigate();
navigate("/login");

I observed the following behavior:

The loader function of the /login route executes first. The Home component renders one additional time. Finally, the Login component renders. It is unclear why Home is being rendered again during the transition.

Additionally, the same behavior occurs when navigating back using:

navigate(-1);

After executing navigate(-1) inside the Login component, the Login component renders again before being unmounted, and then the Home component renders.

Is this the expected behavior, or is it a potential issue with React Router?

Home

const Home: React.FC = () => {

    const navigate = useNavigate()

    console.log("home")

    return (
        <section className="home">
            <h1>home</h1>

            <button
                onClick={async() => {

                    navigate("/login")

                }}
            >
                to login button
            </button>

            
        </section>
    )

}

Login

const Login: React.FC = () => {

    const navigate = useNavigate()

    console.log("login")

    return (
        <section className="login">
            <h1>login</h1>
            <button
                onClick={() => {

                    navigate(-1)

                }}
            >
                to test button
            </button>
        </section>
    )

}

router

const router = createBrowserRouter(
    [
        {
            path: "/home",
            loader: () => {

                console.log("home loading")

                return null

            },
            HydrateFallback: () => null,
            lazy: async() => ({ Component: (await import("@/views/home/home")).default })
        },
        {
            path: "/login",
            loader: () => {

                console.log("login loading")

                return null

            },
            HydrateFallback: () => null,
            lazy: async() => ({ Component: (await import("@/views/login/login")).default })
        },
    ],
)

System Info

OS: macOS
Node.js: v22.13.1
pnpm: v9.9.0
react-router-dom: ^7.1.5

Used Package Manager

pnpm

Expected Behavior

Expected Console Output:

Initial render of Home component:

home loading
home

Navigating from Home to Login:

login loading
login

Navigating back from Login to Home:

home loading
home

Actual Behavior

Actual Console Output:

Initial render of Home component:

home loading
home

Navigating from Home to Login:

login loading
home
login

Navigating back from Login to Home:

home loading
login
home

my-react-app.zip

I'm using React Router as a...

library

Reproduction

I have two sibling route components: Home and Login.

When executing the following navigation code in the Home component:

const navigate = useNavigate();
navigate("/login");

I observed the following behavior:

The loader function of the /login route executes first. The Home component renders one additional time. Finally, the Login component renders. It is unclear why Home is being rendered again during the transition.

Additionally, the same behavior occurs when navigating back using:

navigate(-1);

After executing navigate(-1) inside the Login component, the Login component renders again before being unmounted, and then the Home component renders.

Is this the expected behavior, or is it a potential issue with React Router?

Home

const Home: React.FC = () => {

    const navigate = useNavigate()

    console.log("home")

    return (
        <section className="home">
            <h1>home</h1>

            <button
                onClick={async() => {

                    navigate("/login")

                }}
            >
                to login button
            </button>

            
        </section>
    )

}

Login

const Login: React.FC = () => {

    const navigate = useNavigate()

    console.log("login")

    return (
        <section className="login">
            <h1>login</h1>
            <button
                onClick={() => {

                    navigate(-1)

                }}
            >
                to test button
            </button>
        </section>
    )

}

router

const router = createBrowserRouter(
    [
        {
            path: "/home",
            loader: () => {

                console.log("home loading")

                return null

            },
            HydrateFallback: () => null,
            lazy: async() => ({ Component: (await import("@/views/home/home")).default })
        },
        {
            path: "/login",
            loader: () => {

                console.log("login loading")

                return null

            },
            HydrateFallback: () => null,
            lazy: async() => ({ Component: (await import("@/views/login/login")).default })
        },
    ],
)

System Info

OS: macOS
Node.js: v22.13.1
pnpm: v9.9.0
react-router-dom: ^7.1.5

Used Package Manager

pnpm

Expected Behavior

Expected Console Output:

Initial render of Home component:

home loading
home

Navigating from Home to Login:

login loading
login

Navigating back from Login to Home:

home loading
home

Actual Behavior

Actual Console Output:

Initial render of Home component:

home loading
home

Navigating from Home to Login:

login loading
home
login

Navigating back from Login to Home:

home loading
login
home

my-react-app.zip

Share Improve this question edited Feb 18 at 7:05 dyb-dev asked Feb 17 at 11:07 dyb-devdyb-dev 13 bronze badges New contributor dyb-dev is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 3
  • (1) The console.log("home") and console.log("login") run right in the function component body as unintentional side-effects so there's no actual correlation between logs and actual renders to the DOM, and even so, (2) I'm unable to reproduce the logs you claim. I see no issue here other than the unintentional side-effects and/or misunderstanding console logs. – Drew Reese Commented Feb 18 at 3:41
  • Thank you very much for your reply. Perhaps, as you mentioned, these logs aren’t actually related to the DOM rendering, and I may have misunderstood. However, I still have a question: when I navigate between pages, the console output doesn’t match my expectations, and I’m not sure why. I’m uncertain whether there’s an issue with my code or something else. I’ve re-uploaded the code package—my apologies for the previous one, which was incorrect and caused confusion. With the new package, if you run it and switch between pages (and back), you should be able to reproduce the issue I mentioned. – dyb-dev Commented Feb 18 at 7:25
  • I wasn't able to reproduce the log output you described. Think you could create a running CodeSandbox demo that does reproduce the logs that readers could inspect live? – Drew Reese Commented Feb 18 at 17:59
Add a comment  | 

2 Answers 2

Reset to default 0

The current doubts have been resolved. The official statement is that this is the expected behavior with a loader. Since the loader may take a long time to run, the useNavigate hook is re-rendered, which is why an additional log appears in the console. The re-rendering of the useNavigate hook ensures that navigations are performed against the correct location.

Use this method

const router = createBrowserRouter([
  {
      path: "/",
      element: (
          <Suspense fallback={<div>Loading...</div>}>
              <Home />
          </Suspense>
      ),
  },
  {
      path: "/app-two",
      element: (
          <Suspense fallback={<div>Loading...</div>}>
              <Login />
          </Suspense>
      ),
  },
]);

lazy: async () => ({
  Component: (await import("./AppOne")).default,
}),

Here we are letting React Router handle lazy loading so when component load first time it works fine but when we nevigate to the other route React Router was briefly rendering the home component because it was alredy loaded and show HOME component so By wrapping the component in a Suspense we now can have control what to show while our component is load

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论