Navigation Blocking ist eine Möglichkeit, die Navigation zu verhindern. Dies ist typisch, wenn ein Benutzer versucht zu navigieren, während er
In diesen Situationen sollte dem Benutzer eine Aufforderung oder eine benutzerdefinierte Benutzeroberfläche angezeigt werden, um zu bestätigen, dass er weg navigieren möchte.
Navigation Blocking fügt eine oder mehrere Schichten von "Blockern" zur gesamten zugrunde liegenden History API hinzu. Wenn Blockierer vorhanden sind, wird die Navigation über eine der folgenden Methoden pausiert:
Es gibt 2 Möglichkeiten, Navigation Blocking zu verwenden
Stellen wir uns vor, wir möchten die Navigation verhindern, wenn ein Formular schmutzig ist. Wir können dies tun, indem wir den Hook useBlocker verwenden.
import { useBlocker } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
useBlocker({
shouldBlockFn: () => {
if (!formIsDirty) return false
const shouldLeave = confirm('Are you sure you want to leave?')
return !shouldLeave
},
})
// ...
}
import { useBlocker } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
useBlocker({
shouldBlockFn: () => {
if (!formIsDirty) return false
const shouldLeave = confirm('Are you sure you want to leave?')
return !shouldLeave
},
})
// ...
}
shouldBlockFn gibt Ihnen typsicheren Zugriff auf den current und next Standort
import { useBlocker } from '@tanstack/react-router'
function MyComponent() {
// always block going from /foo to /bar/123?hello=world
const { proceed, reset, status } = useBlocker({
shouldBlockFn: ({ current, next }) => {
return (
current.routeId === '/foo' &&
next.fullPath === '/bar/$id' &&
next.params.id === 123 &&
next.search.hello === 'world'
)
},
withResolver: true,
})
// ...
}
import { useBlocker } from '@tanstack/react-router'
function MyComponent() {
// always block going from /foo to /bar/123?hello=world
const { proceed, reset, status } = useBlocker({
shouldBlockFn: ({ current, next }) => {
return (
current.routeId === '/foo' &&
next.fullPath === '/bar/$id' &&
next.params.id === 123 &&
next.search.hello === 'world'
)
},
withResolver: true,
})
// ...
}
Beachten Sie, dass auch wenn shouldBlockFn false zurückgibt, das Browserereignis beforeunload bei Seitenaktualisierungen oder dem Schließen von Tabs immer noch ausgelöst werden kann. Um dies zu kontrollieren, können Sie die Option enableBeforeUnload verwenden, um den beforeunload-Handler bedingt zu registrieren
import { useBlocker } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
useBlocker({
{/* ... */}
enableBeforeUnload: formIsDirty, // or () => formIsDirty
})
// ...
}
import { useBlocker } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
useBlocker({
{/* ... */}
enableBeforeUnload: formIsDirty, // or () => formIsDirty
})
// ...
}
Weitere Informationen zum Hook useBlocker finden Sie in der API-Referenz.
Neben der logischen/hook-basierten Blockierung können Sie die Komponente Block verwenden, um ähnliche Ergebnisse zu erzielen.
import { Block } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
return (
<Block
shouldBlockFn={() => {
if (!formIsDirty) return false
const shouldLeave = confirm('Are you sure you want to leave?')
return !shouldLeave
}}
enableBeforeUnload={formIsDirty}
/>
)
// OR
return (
<Block
shouldBlockFn={() => formIsDirty}
enableBeforeUnload={formIsDirty}
withResolver
>
{({ status, proceed, reset }) => <>{/* ... */}</>}
</Block>
)
}
import { Block } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
return (
<Block
shouldBlockFn={() => {
if (!formIsDirty) return false
const shouldLeave = confirm('Are you sure you want to leave?')
return !shouldLeave
}}
enableBeforeUnload={formIsDirty}
/>
)
// OR
return (
<Block
shouldBlockFn={() => formIsDirty}
enableBeforeUnload={formIsDirty}
withResolver
>
{({ status, proceed, reset }) => <>{/* ... */}</>}
</Block>
)
}
In den meisten Fällen ist die Verwendung von window.confirm in der Funktion shouldBlockFn mit withResolver: false im Hook ausreichend, da dies dem Benutzer klar anzeigt, dass die Navigation blockiert wird, und die Blockierung basierend auf seiner Antwort auflöst.
In einigen Situationen möchten Sie jedoch möglicherweise eine benutzerdefinierte Benutzeroberfläche anzeigen, die absichtlich weniger störend und besser in das Design Ihrer App integriert ist.
Hinweis: Der Rückgabewert von shouldBlockFn löst die Blockierung nicht auf, wenn withResolver true ist.
import { useBlocker } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
const { proceed, reset, status } = useBlocker({
shouldBlockFn: () => formIsDirty,
withResolver: true,
})
// ...
return (
<>
{/* ... */}
{status === 'blocked' && (
<div>
<p>Are you sure you want to leave?</p>
<button onClick={proceed}>Yes</button>
<button onClick={reset}>No</button>
</div>
)}
</>
}
import { useBlocker } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
const { proceed, reset, status } = useBlocker({
shouldBlockFn: () => formIsDirty,
withResolver: true,
})
// ...
return (
<>
{/* ... */}
{status === 'blocked' && (
<div>
<p>Are you sure you want to leave?</p>
<button onClick={proceed}>Yes</button>
<button onClick={reset}>No</button>
</div>
)}
</>
}
import { useBlocker } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
useBlocker({
shouldBlockFn: () => {
if (!formIsDirty) {
return false
}
const shouldBlock = new Promise<boolean>((resolve) => {
// Using a modal manager of your choice
modals.open({
title: 'Are you sure you want to leave?',
children: (
<SaveBlocker
confirm={() => {
modals.closeAll()
resolve(false)
}}
reject={() => {
modals.closeAll()
resolve(true)
}}
/>
),
onClose: () => resolve(true),
})
})
return shouldBlock
},
})
// ...
}
import { useBlocker } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
useBlocker({
shouldBlockFn: () => {
if (!formIsDirty) {
return false
}
const shouldBlock = new Promise<boolean>((resolve) => {
// Using a modal manager of your choice
modals.open({
title: 'Are you sure you want to leave?',
children: (
<SaveBlocker
confirm={() => {
modals.closeAll()
resolve(false)
}}
reject={() => {
modals.closeAll()
resolve(true)
}}
/>
),
onClose: () => resolve(true),
})
})
return shouldBlock
},
})
// ...
}
Ähnlich wie beim Hook gibt die Komponente Block die gleichen Status und Funktionen wie Render Props zurück.
import { Block } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
return (
<Block shouldBlockFn={() => formIsDirty} withResolver>
{({ status, proceed, reset }) => (
<>
{/* ... */}
{status === 'blocked' && (
<div>
<p>Are you sure you want to leave?</p>
<button onClick={proceed}>Yes</button>
<button onClick={reset}>No</button>
</div>
)}
</>
)}
</Block>
)
}
import { Block } from '@tanstack/react-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = useState(false)
return (
<Block shouldBlockFn={() => formIsDirty} withResolver>
{({ status, proceed, reset }) => (
<>
{/* ... */}
{status === 'blocked' && (
<div>
<p>Are you sure you want to leave?</p>
<button onClick={proceed}>Yes</button>
<button onClick={reset}>No</button>
</div>
)}
</>
)}
</Block>
)
}
Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.