useBlocker hook
useBlocker
메서드는 탐색 차단을 조건이 충족될 때 구현하는 hook입니다.
⚠️ 새로운
useBlocker
API는 현재 실험적입니다.
useBlocker options
useBlocker
hook은 하나의 필수 인수로 옵션 객체를 받습니다:
options.shouldBlockFn
option
- 필수
- 타입:
ShouldBlockFn
- 이 함수는 차단기가 현재 탐색을 차단해야 하는지를 나타내는
boolean
또는Promise<boolean>
을 반환해야 합니다. - 함수는
ShouldBlockFnArgs
타입의 인수를 전달받으며, 이는 현재 및 다음 route와 수행된 작업에 대한 정보를 제공합니다. - 이 함수를 라우터가 탐색을 차단해야 하는지를 알려주는 역할로 생각하세요. 따라서
true
를 반환하면 탐색을 차단하고,false
를 반환하면 탐색이 허용됩니다.
interface ShouldBlockFnLocation<...> {
routeId: TRouteId
fullPath: TFullPath
pathname: string
params: TAllParams
search: TFullSearchSchema
}
type ShouldBlockFnArgs = {
current: ShouldBlockFnLocation
next: ShouldBlockFnLocation
action: HistoryAction
}
options.disabled
option
- 선택적 - 기본값:
false
- 타입:
boolean
- 차단기를 완전히 비활성화할지 여부를 지정합니다.
options.enableBeforeUnload
option
- 선택적 - 기본값:
true
- 타입:
boolean | (() => boolean)
- 브라우저의
beforeUnload
이벤트를 항상 또는 조건부로 차단할지 여부를 설정합니다.
options.withResolver
option
- 선택적 - 기본값:
false
- 타입:
boolean
- hook에서 반환된 resolver를 사용할지 또는
shouldBlockFn
함수 자체가 차단을 해결할지를 지정합니다.
options.blockerFn
option (⚠️ deprecated)
- 선택적
- 타입:
BlockerFn
- 탐색을 허용할지 여부를 나타내는
boolean
또는Promise<boolean>
을 반환하는 함수입니다.
options.condition
option (⚠️ deprecated)
- 선택적 - 기본값:
true
- 타입:
boolean
- 이 조건이
true
일 때 탐색 시도가 차단됩니다.
useBlocker returns
탐색의 수동 차단 및 차단 해제를 제어할 수 있는 객체를 반환합니다.
status
-'blocked'
또는'idle'
중 하나인 문자열 리터럴next
-status
가blocked
일 때, 다음 위치에 대한 정보를 포함하는 타입 내로잉 가능한 객체current
-status
가blocked
일 때, 현재 위치에 대한 정보를 포함하는 타입 내로잉 가능한 객체action
-status
가blocked
일 때, 탐색을 트리거한 작업을 나타내는HistoryAction
문자열proceed
-status
가blocked
일 때, 탐색을 계속할 수 있는 함수reset
-status
가blocked
일 때, 탐색을 취소하는 함수 (status
는'idle'
로 재설정됩니다)
또는
withResolver
가 false
일 때 void
Examples
useBlocker
hook의 일반적인 두 가지 사용 사례:
Basic usage
import { useBlocker } from "@tanstack/react-router";
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false);
useBlocker({
shouldBlockFn: () => formIsDirty,
});
// ...
}
Custom UI
import { useBlocker } from "@tanstack/react-router";
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false);
const { proceed, reset, status, next } = useBlocker({
shouldBlockFn: () => formIsDirty,
withResolver: true,
});
// ...
return (
<>
{/* ... */}
{status === "blocked" && (
<div>
<p>{next.pathname}로 이동 중입니다.</p>
<p>정말로 떠나시겠습니까?</p>
<button onClick={proceed}>예</button>
<button onClick={reset}>아니오</button>
</div>
)}
</>
);
}
Conditional blocking
import { useBlocker } from "@tanstack/react-router";
function MyComponent() {
const { proceed, reset, status } = useBlocker({
shouldBlockFn: ({ next }) => {
return !next.pathname.includes("step/");
},
withResolver: true,
});
// ...
return (
<>
{/* ... */}
{status === "blocked" && (
<div>
<p>정말로 떠나시겠습니까?</p>
<button onClick={proceed}>예</button>
<button onClick={reset}>아니오</button>
</div>
)}
</>
);
}
Without resolver
import { useBlocker } from "@tanstack/react-router";
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false);
useBlocker({
shouldBlockFn: ({ next }) => {
if (next.pathname.includes("step/")) {
return false;
}
const shouldLeave = confirm("정말로 떠나시겠습니까?");
return !shouldLeave;
},
});
// ...
}
Type narrowing
import { useBlocker } from "@tanstack/react-router";
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false);
// editor-1에서 /foo/123?hello=world로 이동을 차단
const { proceed, reset, status } = useBlocker({
shouldBlockFn: ({ current, next }) => {
if (
current.routeId === "/editor-1" &&
next.fullPath === "/foo/$id" &&
next.params.id === "123" &&
next.search.hello === "world"
) {
return true;
}
return false;
},
enableBeforeUnload: false,
withResolver: true,
});
// ...
}