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
相关产品推荐
相关产品推荐

