日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

react-router?重新加回跳轉攔截功能詳解_React

作者:馬格納斯 ? 更新時間: 2023-04-18 編程語言

前言

路由的跳轉攔截,在一些表單頁中尤為常見。場景:用戶輸入了一些信息后但未提交,為了防止用戶誤點擊某個跳轉鏈接導致所填的表單信息丟失,跳轉之前會彈出一個提示,如 “信息未提交,請確認是否離開” 等字樣。

事件經過

react-router v6 之前有提供一個 <Prompt /> 組件來攔截路由的跳轉。而在 v6 中卻不支持此功能了!社區一片哀嚎,經查在 v6 實驗階段是有此功能的,但在 v6.0.0 beta-7 中刪除了此功能。在這個 issue 鏈接 中每個人都強烈要求需要此功能,但官方回復會在不久的將來添加,有需要的可以回退到 v5,基本所有人都表示 ??。然而這一等就是一年多,很多人這期間在 issue 中表示非常失望,這個不久的將來 到底還有沒有了?終于在 v6.7.0 重新加入了此功能,原來不久的將來約等于一年。

v6 之前的版本如何攔截

在你需要攔截的頁面添加 <Prompt /> 組件,我們在輸入框中有值,且進行跳轉頁面時進行攔截。當 when 為 true 時,執行跳轉會觸發攔截操作,message 為提示。

function Home() {
  const [value, setValue] = useState("");
  return (
    <div>
      <Link to="/about" />
      <input value={value} onChange={e => setValue(e.target.value)} />
      <Prompt when={!!value} message="確認要離開嗎" />
    </div>
  );
}

彈出的提示進行自定義,when 可以設置為一個函數,參數為 locationaction(行為),返回 string | boolean。返回 stringtrue 就是直接離開了。

function Home() {
  const [value, setValue] = useState("");
  const history = useHistory();
  return (
    <div>
      <Link to="/about" />
      <input value={value} onChange={(e) => setValue(e.target.value)} />
      <Prompt
        when={!!value}
        message={(location, action) => {
          Modal.confirm({
            message: "確定要離開嗎",
            onOk: () => {
              history.push(location.pathname);
            },
          });
          return false;
        }}
      />
    </div>
  );
}

v6.7.0+ 如何攔截

在這個版本中提供了一個 unstable_useBlocker 鉤子,但在文檔中是沒有的(艸),需要自己去 examples 里找。useBlocker 傳入的參數類似于上面的 when

useBlocker 的參數為 boolean函數返回 boolean,函數的類型如下:

(args: {
    currentLocation: Location;
    nextLocation: Location;
    historyAction: HistoryAction;
}) =&gt; boolean

blocker 里的 stateblocked 時,說明當前正在進行攔截,此時彈出一個 Modal,點擊確認就是進行跳轉,點擊取消就是不跳轉。blocked 中還能獲取到 location,可以根據你的需要來使用。

import { unstable_useBlocker as useBlocker } from "react-router-dom";
function Home() {
  const [value, setValue] = useState("");
  const blocker = useBlocker(!!value);
  useEffect(() => {
    if (blocker.state === "blocked") {
      Modal.confirm({
        message: "確認離開嗎",
        onOk: () => {
          blocker.proceed?.();
        },
        onCancel: () => {
          blocker.reset?.();
        },
      });
    }
  }, [blocker]);
  return (
    <div>
      <Link to="/about" />
      <input value={value} onChange={(e) => setValue(e.target.value)} />
    </div>
  );
}

吐槽

最后,就在這里吐槽一下吧。文檔很爛,不支持搜索!且 v6.4 的后續版本中加入了很多 api,例如 actionloader 的概念,跟數據請求有關。但是我覺得很難用,路由庫就應該只專注路由,應該跟它們的 remix 框架的發展有關吧。官方的權限控制例子也是不好用,很麻煩。下個文章會寫在 v6 中如何優雅簡單的管理權限。

原文鏈接:https://juejin.cn/post/7193909961305358394

欄目分類
最近更新