Closed3
react-router-dom の Prompt と createBrowserRouter
- react-router-dom v6 から v5 で存在した
<Prompt />
が消えた。- その件の詳細はこのスレッドで議論されてる
- https://github.com/remix-run/react-router/issues/8139
- chaanceさんが
<Prompt />
の実装を gist に載せてる - v5
<Prompt />
との変更点としては message で以前は function に対応していたけど忘れられてた- 自力で書いてみる
import { useCallback, useRef, useEffect } from 'react'
import {
unstable_useBlocker as useBlocker,
unstable_BlockerFunction as BlockerFunction,
Location,
} from 'react-router-dom'
export type BlockerFunctionArgs = Parameters<BlockerFunction>[0]
export type HistoryAction = BlockerFunctionArgs['historyAction']
function usePrompt(
message: string | BlockerFunction | null | undefined | false
) {
const blocker = useBlocker(
useCallback(
(args: {
currentLocation: Location
nextLocation: Location
historyAction: HistoryAction
}) => {
if (typeof message === 'function') {
return !message(args)
} else if (typeof message === 'string') {
return !window.confirm(message)
} else {
return false
}
},
[message]
)
)
const prevState = useRef(blocker.state)
useEffect(() => {
if (blocker.state === 'blocked') {
blocker.reset()
}
prevState.current = blocker.state
}, [blocker])
}
export function Prompt({ when, message }: PromptProps) {
usePrompt(when ? message : false)
return null
}
interface PromptProps {
when: boolean
message: string | BlockerFunction
}
-
useBeforeUnload
は function にそもそも対応してないので今回は削除した
- 書いてみたがエラーになる。
- どうやら
unstable_useBlocker
などの data API を使うためにはcreateBrowserRouter
を使う必要があるみたい - https://reactrouter.com/en/main/routers/picking-a-router
- どうやら
- さすがに全部を
createBrowserRouter
方式に書き換えるのは無理なので全体を囲むように修正
+ import { createBrowserRouter, RouterProvider } from 'react-router-dom'
+ const router = createBrowserRouter([{ path: '*', Component: App }])
<SomeProviders>
- <BrowserRouter>
- <App />
- </BrowserRouter>
+ <RouterProvider router={router} />;
</SomeProviders>
動いたので、おしまい。
このスクラップは2023/06/06にクローズされました