gpt4 book ai didi

javascript - 如何使用react-router 显示组件以防止或允许路由更改

转载 作者:行者123 更新时间:2023-12-02 23:27:40 24 4
gpt4 key购买 nike

我目前正在尝试找到一种方法来显示自定义组件(如模态)以使用 Prompt 确认路线更改组件。

Promp 的默认行为组件的作用是显示一个带有消息的确认对话框,如您在 Example: React Router: Preventing Transitions. 中看到的那样

注意:我正在使用<BrowserRouter>组件。

路由器有 prop命名getUserConfirmation ,您可以使用它来自定义 <Prompt> 的行为组件。

// this is the default behavior

function getConfirmation(message, callback) {
const allowTransition = window.confirm(message);
callback(allowTransition);
}

<BrowserRouter getUserConfirmation={getConfirmation} />;

我正在尝试做什么:

  • 父组件APP内
    • 我正在设置 confirm状态为true,显示<Confirm>组件
    • 我正在尝试通过 callback来自getConfirmation功能到<Confirm>组件以 true 调用它允许过渡,并使用 false来防止它。
    • 将使用 true or false 调用回调正如您在上面看到的默认行为。
function getConfirmation(message, callback) {
console.log("Inside getConfirmation function...");
setConfirmCallback(callback);
setConfirm(true);
// const allowTransition = window.confirm(message);
// callback(allowTransition);
}

这就是 App.js 正在渲染的内容:

return (
<Router getUserConfirmation={getConfirmation}>
<AllRoutes />
{confirm && (
<Confirm confirmCallback={confirmCallback} setConfirm={setConfirm} />
)}
</Router>
);

问题所在:

  • confirm对话框似乎在此时阻止了该功能。所以callback变量/参数仍在范围内。所以一切正常。
  • 当我删除 confirm 时对话框中,该函数一直运行。当我单击 <Confirm> 内的确认按钮时组件,callback不再存在。

问题

有谁知道使用 react-router-dom 实现此行为的方法(使用自定义组件而不是确认对话框来防止路由更改) ?

Link to CodeSandbox

来自 CodeSandbox 的完整代码:

import React, { useState } from "react";
import ReactDOM from "react-dom";
import {
BrowserRouter as Router,
Route,
Switch,
Link,
Prompt
} from "react-router-dom";

import "./styles.css";

function App() {
console.log("Rendering App...");

const [confirm, setConfirm] = useState(false);
const [confirmCallback, setConfirmCallback] = useState(null);

function getConfirmation(message, callback) {
console.log("Inside getConfirmation function...");
setConfirmCallback(callback);
setConfirm(true);
// const allowTransition = window.confirm(message);
// callback(allowTransition);
}

return (
<Router getUserConfirmation={getConfirmation}>
<AllRoutes />
{confirm && (
<Confirm confirmCallback={confirmCallback} setConfirm={setConfirm} />
)}
</Router>
);
}

function Confirm(props) {
function allowTransition() {
props.setConfirm(false);
props.confirmCallback(true);
}

function blockTransition() {
props.setConfirm(false);
props.confirmCallback(false);
}

return (
<React.Fragment>
<div>Are you sure?</div>
<button onClick={allowTransition}>Yes</button>
<button onClick={blockTransition}>No way</button>
</React.Fragment>
);
}

function AllRoutes(props) {
console.log("Rendering AllRoutes...");
return (
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/comp1" component={Component1} />
</Switch>
);
}

function Home(props) {
console.log("Rendering Home...");
return (
<React.Fragment>
<div>This is Home</div>
<ul>
<li>
<Link to="/comp1">Component1</Link>
</li>
</ul>
</React.Fragment>
);
}

function Component1(props) {
console.log("Rendering Component1...");

const [isBlocking, setIsBlocking] = useState(true);

return (
<React.Fragment>
<Prompt
when={isBlocking}
message={location =>
`Are you sure you want to go to ${location.pathname}`
}
/>
<div>This is component 1</div>
<Link to="/">Home</Link>
</React.Fragment>
);
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

最佳答案

受到此启发discussion并由此 example ,我能够使我的示例正常工作。

问题是当 <Confirm>正在创建,setConfirmCallback()通话尚未完成。所以<Confirm>组件无法使用 callback来自getUserConfirmation .

所以我改变了这一行:

FROM:
setConfirmCallback(callback);
TO:
setConfirmCallback(()=>callback);

现在可以了!

CodeSandbox Link

完整的CodeSandbox代码:

import React, { useState } from "react";
import ReactDOM from "react-dom";
import {
BrowserRouter as Router,
Route,
Switch,
Link,
Prompt
} from "react-router-dom";

import "./styles.css";

function App() {
console.log("Rendering App...");

const [confirm, setConfirm] = useState(false);
const [confirmCallback, setConfirmCallback] = useState(null);

function getConfirmation(message, callback) {
console.log("Inside getConfirmation function...");
setConfirmCallback(() => callback);
setConfirm(true);
// const allowTransition = window.confirm(message);
// callback(allowTransition);
}

return (
<Router getUserConfirmation={getConfirmation}>
<AllRoutes />
{confirm && (
<Confirm confirmCallback={confirmCallback} setConfirm={setConfirm} />
)}
</Router>
);
}

function Confirm(props) {
console.log("Rendering Confirm...");
function allowTransition() {
props.setConfirm(false);
props.confirmCallback(true);
}

function blockTransition() {
props.setConfirm(false);
props.confirmCallback(false);
}

return (
<React.Fragment>
<div>Are you sure?</div>
<button onClick={allowTransition}>Yes</button>
<button onClick={blockTransition}>No way</button>
</React.Fragment>
);
}

function AllRoutes(props) {
console.log("Rendering AllRoutes...");
return (
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/comp1" component={Component1} />
</Switch>
);
}

function Home(props) {
console.log("Rendering Home...");
return (
<React.Fragment>
<div>This is Home</div>
<ul>
<li>
<Link to="/comp1">Component1</Link>
</li>
</ul>
</React.Fragment>
);
}

function Component1(props) {
console.log("Rendering Component1...");

const [isBlocking, setIsBlocking] = useState(true);

return (
<React.Fragment>
<Prompt
when={isBlocking}
message={location =>
`Are you sure you want to go to ${location.pathname}`
}
/>
<div>This is component 1</div>
<Link to="/">Home</Link>
</React.Fragment>
);
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

关于javascript - 如何使用react-router <Prompt>显示组件以防止或允许路由更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56664622/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com