useBlocker
本页内容

useBlocker

摘要

参考文档 ↗

允许应用程序阻止 SPA 内的导航,并向用户显示一个确认对话框以确认导航。主要用于避免丢失填写了一半的表单数据。这不处理硬刷新或跨域导航。

该钩子返回的 Blocker 对象具有以下属性

  • state
    • unblocked - 阻塞器处于空闲状态,未阻止任何导航
    • blocked - 阻塞器已阻止一次导航
    • proceeding - 阻塞器正在从一次被阻止的导航中继续进行
  • location
    • 当处于 blocked 状态时,这代表我们阻止导航到的 Location。当处于 proceeding 状态时,这是在调用 blocker.proceed() 后正在导航到的位置。
  • proceed()
    • 当处于 blocked 状态时,您可以调用 blocker.proceed() 来继续前往被阻止的位置。
  • reset()
    • 当处于 blocked 状态时,您可以调用 blocker.reset() 将阻塞器返回到 unblocked 状态,并让用户停留在当前位置。
// Boolean version
let blocker = useBlocker(value !== "");

// Function version
let blocker = useBlocker(
  ({ currentLocation, nextLocation, historyAction }) =>
    value !== "" &&
    currentLocation.pathname !== nextLocation.pathname
);

签名

function useBlocker(shouldBlock: boolean | BlockerFunction): Blocker

参数

shouldBlock

一个布尔值或一个返回布尔值的函数,用于指示是否应阻止导航。函数格式接收一个包含潜在导航的 currentLocationnextLocationhistoryAction 的对象参数。

返回

一个具有状态和重置功能的 Blocker 对象

示例

import { useCallback, useState } from "react";
import { BlockerFunction, useBlocker } from "react-router";

export function ImportantForm() {
  const [value, setValue] = useState("");

  const shouldBlock = useCallback<BlockerFunction>(
    () => value !== "",
    [value]
  );
  const blocker = useBlocker(shouldBlock);

  return (
    <form
      onSubmit={(e) => {
        e.preventDefault();
        setValue("");
        if (blocker.state === "blocked") {
          blocker.proceed();
        }
      }}
    >
      <input
        name="data"
        value={value}
        onChange={(e) => setValue(e.target.value)}
      />

      <button type="submit">Save</button>

      {blocker.state === "blocked" ? (
        <>
          <p style={{ color: "red" }}>
            Blocked the last navigation to
          </p>
          <button
            type="button"
            onClick={() => blocker.proceed()}
          >
            Let me through
          </button>
          <button
            type="button"
            onClick={() => blocker.reset()}
          >
            Keep me here
          </button>
        </>
      ) : blocker.state === "proceeding" ? (
        <p style={{ color: "orange" }}>
          Proceeding through blocked navigation
        </p>
      ) : (
        <p style={{ color: "green" }}>
          Blocker is currently unblocked
        </p>
      )}
    </form>
  );
}
文档和示例 CC 4.0
编辑