I have provider which makes a request to the server to refresh a token and has some values. Also I have a simple layout with a sidebar. I wanna use them only in one route. Idk where to add the layout and I've already used Outlet in the provider
Provider:
export const AuthProvider: FC = () => {
const [isUserLoged, setIsUserLoged] = useState(false)
const [isAppReady, setIsAppReady] = useState(false)
useEffect(() => {
AuthClient.post("/refresh").then((res: AxiosResponse) => {
const {accessToken, accessTokenExpiration} = res.data;
inMemoryJWT.setToken(accessToken, accessTokenExpiration)
setIsAppReady(true)
setIsUserLoged(true)
}).catch((err) => {
setIsAppReady(true)
toast.error(err.response.data.error)
})
}, [])
useEffect(() => {
const handlePersistedLogOut = (e: StorageEvent) => {
if(e.key === config.LOGOUT_STORAGE_KEY) {
inMemoryJWT.deleteToken()
setIsUserLoged(false)
}
}
return window.addEventListener("storage", handlePersistedLogOut)
}, [])
return (
<AuthContext.Provider
value={{
isAppReady,
isUserLoged,
}}
>
<Outlet />
</AuthContext.Provider>
);
};
Routing:
export const Routers: FC = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<AuthProvider />}>
<Route path="/home" element={<div>Home</div>} />
</Route>
<Route path="/auth" element={<Auth />} />
<Route path="*" element={<ErrorPage message="Страница не найдена!" status={404} />} />
</Routes>
</BrowserRouter>
)
}
There is really no need to "do it all in one route" when layout routes can be pathless. Pathless routes only contribute to the UI, nothing to the URL path.
A trivial solution is to use separate layout routes for separate concerns.
Example:
export const Routers: FC = () => {
return (
<BrowserRouter>
<Routes>
<Route element={<AuthProvider />}> // <-- pathless
<Route element={<Layout />}> // <-- pathless
<Route path="/home" element={<div>Home</div>} />
</Route>
</Route>
<Route path="/auth" element={<Auth />} />
<Route
path="*"
element={<ErrorPage message="Страница не найдена!" status={404} />}
/>
</Routes>
</BrowserRouter>
);
};
If you have layout components that are commonly used together then you can abstract these into a single layout.
Example:
export const AuthProvider = ({ children }) => {
...
return (
<AuthContext.Provider
value={{
isAppReady,
isUserLoged,
}}
>
{children}
</AuthContext.Provider>
);
};
const Layout = ({ children }) => {
...
return (
...
{children}
...
);
};
const AuthLayout = () => (
return (
<AuthProvider>
<Layout>
<Outlet />
</Layout>
</AuthProvider>
);
);
export const Routers: FC = () => {
return (
<BrowserRouter>
<Routes>
<Route element={<AuthLayout />}> // <-- pathless
<Route path="/home" element={<div>Home</div>} />
</Route>
<Route path="/auth" element={<Auth />} />
<Route
path="*"
element={<ErrorPage message="Страница не найдена!" status={404} />}
/>
</Routes>
</BrowserRouter>
);
};