You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

createBrowserRouter中useNavigate仅改URL不渲染组件求助

问题:React Router登录后URL变化但页面不更新

点击登录按钮后,URL正常变化、toast提示也能显示,但页面内容完全不更新。尝试跳转到member/:memberID、member-info、/等多个路由,问题一致,连首页都无法正常渲染,排除是Protected Route的问题。但在登录页单独加一个按钮<button onClick={() => {navigate('/')}}>gogo</button>,点击后却能正常渲染Home组件。

试过在navigate后调用navigate(0),虽然能渲染组件,但这不是最优方案,求更好的解决办法。


相关代码

main.tsx

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
    <ToastContainer />
  </React.StrictMode>
)

RootLayout.tsx

const RootLayout = () => {
  return (
    <div>
      <Header />
      <Outlet />
      <Footer />
      <ScrollRestoration />
    </div>
  )
}

export default RootLayout

App.tsx

const App: React.FC = () => {
  const router = createBrowserRouter(
    createRoutesFromElements(
      <Route path='/' element={<RootLayout />}>
        <Route index element={<Home />} />
        <Route path='signin' element={<SignIn />} />
        <Route element={<ProtectedRoute />}>
          <Route path='member/:memberID' element={<Member />} />
        </Route>
        <Route path='member-info' element={<ProtectedMemberInfoRoute />} />
        <Route path='*' element={<NoMatch />} />
      </Route>
    )
  )

  return <RouterProvider router={router} />
}

export default App

Signin/index.tsx

const SignIn: React.FC = () => {
  const navigate = useNavigate()
  
  const handleSignIn = async () => {
    try {
      const userCredential = await signInWithEmailAndPassword(auth, userEmail, userPassword)
      const userID = userCredential.user.uid
      const userDoc = await getDoc(doc(db, 'users', userID))

        if (userDoc.data()?.userFinishedInfo) {
          toast.success(`Welcome back, ${userDoc.data()?.username}`, {
            position: 'top-right',
            autoClose: 1000,
            hideProgressBar: false,
            closeOnClick: false,
            pauseOnHover: false,
            draggable: false,
            progress: undefined,
            theme: 'light'
          })
          navigate(`/member/${userID}`)
        } else {
          toast.warn(`You haven't finish your profile`, {
            position: 'top-right',
            autoClose: 1000,
            hideProgressBar: false,
            closeOnClick: false,
            pauseOnHover: false,
            draggable: false,
            progress: undefined,
            theme: 'light'
          })
          navigate('/member-info')
        }
      })
      .catch((error) => {
        console.error(error)
        toast.warn(`Incorrect email or password`, {
          position: 'top-right',
          autoClose: 1000,
          hideProgressBar: false,
          closeOnClick: false,
          pauseOnHover: false,
          draggable: false,
          progress: undefined,
          theme: 'light'
        })
      })
  }

  return (
    <div className='h-screen-256px flex w-full flex-col items-center justify-center'>
      ...
      <button
        className='h-fit w-fit rounded-full bg-blue-500 p-4 text-white hover:bg-blue-600'
        onClick={() => handleSignIn()}
      >
        Sign In
      </button>
      <button
        onClick={() => {
          navigate('/')
        }}
      >
        gogo
      </button>
    </div>
  )
}

export default SignIn

package.json

"dependencies": {
  ...
  "react": "18.2.0",
  "react-dom": "18.2.0",
  "react-toastify": "9.1.3",
  "zustand": "4.4.7",
  "@firebase/firestore": "4.4.0",
  "uuid": "9.0.1",
  "tailwindcss": "3.3.6",
  "firebase": "10.7.1",
  "react-router-dom": "6.21.0"
},

2023.12.18 更新:问题解决

已找到流畅的解决方案,思路如下:

  • 创建路由守卫组件包裹SignIn组件
  • 使用<Navigate>元素实现跳转,替代在handleSignIn函数中调用useNavigate()

修改后代码

ProtectedSignInRoute.tsx

import { Navigate } from 'react-router-dom'
import SignIn from '../../pages/Signin'
import { useUserStore } from '../../store/useUser'

const ProtectedSignInRoute = () => {
  const { isSignIn, userID, isLoadedUserDoc, userDoc } = useUserStore()

  if (isLoadedUserDoc && isSignIn && userDoc?.userFinishedInfo) {
    return <Navigate to={`/member/${userID}`} />
  } else if (isLoadedUserDoc && isSignIn && !userDoc?.userFinishedInfo) {
    return <Navigate to='/member-info' />
  } else {
    return <SignIn />
  }
}

export default ProtectedSignInRoute

App.tsx

const App: React.FC = () => {
  const router = createBrowserRouter(
    createRoutesFromElements(
      <Route path='/' element={<RootLayout />}>
        <Route index element={<Home />} />
        <Route path='signin' element={<ProtectedSignInRoute />} /> // 此处修改
        <Route element={<ProtectedRoute />}>
          <Route path='member/:memberID' element={<Member />} />
        </Route>
        <Route path='member-info' element={<ProtectedMemberInfoRoute />} />
        <Route path='*' element={<NoMatch />} />
      </Route>
    )
  )

  return <RouterProvider router={router} />
}

export default App

内容的提问来源于stack exchange,提问作者Hollow Knight Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 03:45:02