我有这个自定义挂钩登录和注销
export function useUser() {
const { token, setToken, user, setUser } = useContext(AuthContext)
const navigate = useNavigate()
const {
mutate: login,
isLoading: isLoginLoading,
isError: hasLoginError,
} = useMutation({
mutationFn: signIn,
onSuccess: async (tokenResponse) => {
sessionStorage.setItem('access_token', tokenResponse.access_token)
sessionStorage.setItem('refresh_token', tokenResponse.refresh_token)
setToken(tokenResponse.access_token)
const user = await getUserProfile()
setUser(user)
sessionStorage.setItem('userData', JSON.stringify(user))
navigate('/home')
},
onError: () => {
sessionStorage.removeItem('access_token')
}
})
const { mutate: logout } = useMutation({
mutationFn: signOut,
onMutate: () => {
sessionStorage.clear()
setToken(null)
setUser(null)
},
onSuccess: async () => {
navigate('/login')
}
})
return {
login,
logout,
isLoginLoading,
hasLoginError,
userPermissions: token ? (jwt_decode(token) as TokenDecoded).authorities : [],
user
}
}
我想利用新的数据路由器react-router-dom createBrowserRouter
,并尝试创建一个breadcrumb。在此之前,我使用<BrowserRouter>
,它工作得很好,但是使用这种新方法,并且由于使用了受保护的路由,我得到了错误。
useNavigate()只能在组件的上下文中使用。
我完全理解这个错误,但我不知道如何使它工作。这与我发布的另一个问题this issue和一个类似的问题similar issue有关。下面是我的代码:CommonLayout.tsx and AuthLayout.tsx
export const CommonLayout = ({ isAllowed }: Props) => {
return (
<div className='flex flex-col h-screen'>
{isAllowed ? <Navbar /> : <GuestNavbar />}
<main className='flex-1 min-h-max p-8 bg-slate-100 dark:bg-neutral-800'>
<Outlet />
</main>
<Footer />
</div>
)
}
export const AuthLayout = ({ isAllowed, redirectPath, children }: Props) => {
const location = useLocation()
return isAllowed ? (
children ?? <Outlet />
) : (
<Navigate to={redirectPath} replace state={{ from: location }} />
)
}
我想要的新方法是:
export function App() {
const { user, userPermissions } = useUser()
const router = createBrowserRouter(
createRoutesFromElements(
<>
<Route element={<CommonLayout isAllowed={!!user} />}>
<Route path='login' element={<Login />} />
<Route element={<AuthLayout isAllowed={userPermissions.includes('PERMISSION_1')} redirectPath='/login' />}>
<Route
path='home'
element={
<>
<Breadcrumbs />
<h1>Home</h1>
</>
}
handle={{ crumb: () => 'Home' }}
/>
<Route
path='tracking'
element={
<Suspense fallback={<>...</>}>
<Breadcrumbs />
<Tracking />
</Suspense>
}
handle={{ crumb: () => 'Tracking' }}
/>
<Route
path='cleaning'
element={
<Suspense fallback={<>...</>}>
<Breadcrumbs />
<Cleaning />
</Suspense>
}
/>
<Route
path='admin'
element={
<Suspense fallback={<>...</>}>
<Breadcrumbs />
<Admin />
</Suspense>
}
handle={{ crumb: () => 'Admin' }}
/>
</Route>
</Route>
<Route path='*' element={<Navigate to='/home' replace />} />
</>
)
)
return <RouterProvider router={router} />
}
如您所见,我需要user
,因为有些路由需要它,但是导入钩子会抛出错误。我该如何避免这种情况?
第一种方法是从钩子useUser中删除useNavigate
。
第二个是修改布局,这样布局就可以导入钩子,并作为参数接收权限(如果是权限)和条件(如果我需要)
先谢谢你了
1条答案
按热度按时间xytpbqjk1#
useUser
钩子只能在路由器提供的路由上下文中调用,因此需要移动它。第二个是修改布局,这样布局就可以导入钩子,并作为参数接收权限(在权限的情况下)和条件(在我需要的情况下)。
这是我推荐的方法。
useUser
钩子已经阅读了我假设的一个全局AuthContext
值,所以从我所看到的来看,将useUser
钩子调用向下推送到ReactTree中需要它的组件是完全安全的。更新布局组件以访问
useUser
钩子值并将静态数据作为props传入。相应地更新布局管线元件。
CommonLayout
现在不使用任何props,并且AuthLayout
被传递了一个角色/权限数组。删除useUser
钩子调用。