我目前正在尝试找到一种方法来显示自定义组件(如 Modal)以使用该Prompt组件确认路由更改。
组件的默认行为Promp是显示带有消息的确认对话框,如您在此示例中所见:React Router:防止转换。
注意:我正在使用该<BrowserRouter>组件。
路由器有一个propnamed 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?
来自 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);