useBlocker hook
useBlocker 메서드는 탐색 차단을 조건이 충족될 때 구현하는 hook입니다.
⚠️ 새로운
useBlockerAPI는 현재 실험적입니다.
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,
});
// ...
}