Skip to content

Instantly share code, notes, and snippets.

@lopo12123
Created November 10, 2024 14:36
Show Gist options
  • Save lopo12123/2ab8625df85999235252fa75fd34c61f to your computer and use it in GitHub Desktop.
Save lopo12123/2ab8625df85999235252fa75fd34c61f to your computer and use it in GitHub Desktop.
react-router dataStrategy
import { createHashRouter, DataStrategyFunction, DataStrategyResult, Outlet, RouterProvider } from "react-router-dom";
import { createRoot } from "react-dom/client";
// global user state management
abstract class User {
static token: string | null = 'expired token'
static async refreshToken(): Promise<boolean> {
await new Promise((resolve) => setTimeout(resolve, 1000))
const random = Math.random()
// success to refresh token
if(random > 0.5) {
User.token = 'new token'
return true
}
// failed to refresh token (the refresh token is expired)
return false
}
static async functionCall() {
console.log('functionCall with token', User.token)
return { result: 'success' }
}
}
// root layout
const RootLayout = () => <Outlet/>
// refresh access token before rendering the page,
// or redirect to the auth page if the refresh token is expired
RootLayout.loader = async () => {
const isRefreshed = await User.refreshToken()
console.log('isRefreshed', isRefreshed)
// if the refresh token is expired, redirect to the auth page
// if(!isRefreshed) return replace('/auth')
// otherwise, keep the current page
return null
}
// specific function page
const FunctionPage = () => {
return (
<div>
<h1>User Page</h1>
<p>name: { User.name }</p>
</div>
)
}
// load some data before rendering the page
FunctionPage.loader = () => User.functionCall()
// custom data strategy to handle the loader
const dataStrategy: DataStrategyFunction = async ({ matches }) => {
// filter the matches that have loader
const matchesWithLoader = matches.filter(m => m.shouldLoad)
const results: { [k: string]: DataStrategyResult } = {}
// ensure all loaders are executed in order
for (const match of matchesWithLoader) {
try {
results[match.route.id] = await match.resolve()
} catch (err) {
results[match.route.id] = { type: 'error', result: err }
}
}
return results
}
const router = createHashRouter([
{
element: <RootLayout/>,
loader: RootLayout.loader,
children: [
{
path: '/auth',
element: <div>Auth Page</div>
},
{
path: '/function-call',
loader: FunctionPage.loader,
element: <FunctionPage/>
}
],
}
], {
dataStrategy
})
// entry point
createRoot(document.getElementById('root')!)
.render(<RouterProvider router={ router }/>)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment