React Router Dom - v6 - useBlocker

Vel*_*o89 8 reactjs react-router-dom react-hooks

由于https://github.com/remix-run/react-router/issues/8139已完成并且我们进入useBlocker了 v6,有人让它工作吗?

这是我到目前为止所得到的,几乎我陷入了我完全不明白的错误

在 App.js 中我有我的BrowserRouter并且所有东西都包含在里面

我还使用了实施者要点中的示例(我复制粘贴)

import * as React from "react";
import { useBeforeUnload, unstable_useBlocker as useBlocker } from "react-router-dom";

function usePrompt(message, { beforeUnload } = {}) {

let blocker = useBlocker(
  React.useCallback(
     () => (typeof message === "string" ? !window.confirm(message) : false),
  [message]
  )
);
let prevState = React.useRef(blocker.state);

React.useEffect(() => {
    if (blocker.state === "blocked") {
    blocker.reset();
  }
  prevState.current = blocker.state;
}, [blocker]);

useBeforeUnload(
     React.useCallback(
       (event) => {
         if (beforeUnload && typeof message === "string") {
          event.preventDefault();
          event.returnValue = message;
         }
      },
      [message, beforeUnload]
    ),
  { capture: true }
 );
}

function Prompt({ when, message, ...props }) {
    usePrompt(when ? message : false, props);
    return null;
}
Run Code Online (Sandbox Code Playgroud)

然后在我的组件中我Prompt这样调用

const MyComponent = (props) => {
    const [showPrompt, setShowPrompt] = useState(false)

    ...

    return (
        ...
        <Prompt when={showPrompt} 
                message="Unsaved changes detected, continue?" 
                beforeUnload={true} 
        />
    )
}
Run Code Online (Sandbox Code Playgroud)

在页面加载时MyComponent我不断收到错误

Error: useBlocker must be used within a data router.  See 
    https://reactrouter.com/routers/picking-a-router.
     at invariant (history.ts:308:1)
     at useDataRouterContext (hooks.tsx:523:1)
     at useBlocker (hooks.tsx:723:1)
     at usePrompt (routerCustomPrompt.js:8:1)
     at Prompt (routerCustomPrompt.js:37:1)
Run Code Online (Sandbox Code Playgroud)

有人进入useBlocker新版本工作了吗?

nes*_*ink 6

useBlocker由于我在理解如何让这个钩子和组件工作方面遇到了一些困难Prompt,因此我将详细说明我必须做的代码更改才能使其与react-router-domversion一起工作6.10.0

首先,请参阅Using v6.4 Data APIs In v6.4的文档,其中建议使用新的数据API,特别createBrowserRouter是代替<BrowserRouter>.

根据文档,<BrowserRouter>基于的声明不“支持数据 API”,这反过来会导致Error: useBlocker must be used within a data router.

因此,在我的应用程序中,我最终替换了路线声明:

export default function App() {
  return (
    <YourProviders>
      <BrowserRouter>
        <Routes>
          // your routes
        </Routes>
      </BrowserRouter>
    </YourProviders>
  );
}

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />);
Run Code Online (Sandbox Code Playgroud)

const router = createBrowserRouter(
  createRoutesFromElements(
    <Routes>
      // your routes
    </Routes>
  )
);

export default function App() {
  return (
    <YourProviders>
      <RouterProvider router={router} />
    </YourProviders>
  );
}

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />);

Run Code Online (Sandbox Code Playgroud)

这最终又按Prompt预期工作了。


Dre*_*ese 1

错误信息相当清楚。为了使用该钩子,必须在数据路由器呈现的组件中使用useBlocker它。请参阅选择路由器

例子:

const MyComponent = (props) => {
  const [showPrompt, setShowPrompt] = useState(false);

  ...

  return (
    ...
    <Prompt
      when={showPrompt} 
      message="Unsaved changes detected, continue?" 
      beforeUnload={true} 
    />
  );
}
Run Code Online (Sandbox Code Playgroud)
import {
  createBrowserRouter,
  createRoutesFromElements,
  Route,
  RouterProvider,
} from "react-router-dom";

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" element={<Root />}>
      {/* ... etc. */}
      <Route path="myComponent" element={<MyComponent />} />
      {/* ... etc. */}
    </Route>
  )
);

const App = () => <RouterProvider router={router} />;
Run Code Online (Sandbox Code Playgroud)