我正在尝试使用自定义对话框要求用户进行确认,然后再浏览未保存的数据。
遵循我拥有的文档:
componentDidMount() {
this.props.router.setRouteLeaveHook(
this.props.route,
this.routerWillLeave
)
}
,而不是
routerWillLeave(nextLocation) {
if (!this.props.pristine) {
return 'You have unsaved information, are you sure you want to leave this page?'
}
我有
routerWillLeave(nextLocation) {
if (!this.props.pristine) {
this.setState({open: true})
this.forceUpdatate() //necessary or else render won't be called to open dialog
}
我正在使用的对话框组件来自材料-UI,它只是期望open
布尔值控制对话框,它也采用handleCancel
和handleContinue
方法,但我不确定如何与routerWillLeave
相连。
handleCancel
方法很简单,因为它只是关闭对话框:
handleCancel() {
this.setState({open: false})
};
我已将对话框组件包装在称为Notification
export default class Notification extends React.Component {
render() {
const { open, handleCancel, handleContinue } = this.props
const actions = [
<FlatButton
label="Cancel"
primary={true}
onTouchTap={handleCancel}
/>,
<FlatButton
label="Continue"
primary={true}
onTouchTap={handleContinue}
/>,
];
return (
<div>
<Dialog
actions={actions}
modal={false}
open={open}
>
You have unsaved data. Discard changes?
</Dialog>
</div>
);
}
}
,我可以从父组件中调用它,我在渲染方法中使用了此内容:
<Notification open={open} handleCancel={this.handleCancel} handleContinue={this.handleContinue}/>
基本上我的问题是如何将其与routerWillLeave
进行连接,而不是显示本机浏览器警报?
调用createHistory
时,它的选项之一是getUserConfirmation
,它采用提示message
和callback
。对于DOM历史记录(browserHistory
和hashHistory
),getUserConfirmation
调用window.confirm
,将其传递给message
。callback
功能接收window.confirm
[0]的返回值。
您需要做的是提供复制window.confirm
的getUserConfirmation
方法。调用时,您应该显示模式并根据单击哪个按钮触发callback
。
Notification.js
<Notification>
组件应采用提示message
,并根据用户的操作来调用callback
函数。
class Notification extends React.Component {
contructor(props) {
this.state = {
open: false
}
}
handleCancel() {
this.props.callback(false)
this.setState({ open: false })
}
handleContinue() {
this.props.callback(true)
this.setState({ open: false })
}
render() {
const { message } = this.props
const { open } = this.state
const actions = [
<FlatButton
label="Cancel"
primary={true}
onTouchTap={this.handleCancel.bind(this)}
/>,
<FlatButton
label="Continue"
primary={true}
onTouchTap={this.handleContinue.bind(this)}
/>,
];
return (
<div>
<Dialog
actions={actions}
modal={true}
open={open}
>
{message}
</Dialog>
</div>
);
}
}
modalConfirmation.js
确认模式不是真正的UI一部分,这就是为什么我在单独的渲染过程中呈现它的原因。
import React from 'react'
import ReactDOM from 'react-dom'
import Notification from './components/Notification'
export default function = (holderID) => {
var modalHolder = document.getElementById(holderID)
return function ModalUserConfirmation(message, callback) {
ReactDOM.render((
<Notification open={true} message={message} callback={callback} />
), modalHolder)
}
}
这显然会迫使您创建自己的历史对象。您不能仅导入browserHistory
或hashHistory
,因为使用window.confirm
。幸运的是,创建自己的历史是微不足道的。这本质上是与browserHistory
[1]中使用的代码相同的代码,但是它通过createBrowserHistory
您的getUserConfirmation
函数。
createConfirmationhishory.js
import createBrowserHistory from 'history/lib/createBrowserHistory'
import createRouterHistory from './createRouterHistory'
export default function(getUserConfirmation) {
return createRouterHistory(createBrowserHistory({
getUserConfirmation
})
}
index.js
最后,您需要将所有这些放在一起。
import createHistory from './createConfirmationHistory'
import ModalConfirmation from './ModalConfirmation'
const getModalConfirmation = ModalConfirmation('modal-holder')
const history = createHistory(getModalConfirmation)
ReactDOM.render((
<Router history={history}>
// ...
</Router>
), document.getElementById('root')
,如果您想使用历史记录单例,则必须对此进行一些重构,但否则它应该起作用。(尽管我实际上还没有测试过)。
[0] https://github.com/mjackson/history/blob/v2.x/modules/domutils.js#l38-l40
[1] https://github.com/reaecttraining/react-router/blob/master/modules/browserhistory.js
您可以尝试使用React-Router-Navigation-Prompt。
这对我有用。
i使用react-router-dom
的Prompt
使用antd
的自定义模式进行了此操作。材料UI应该具有非常相似的功能。
在我的index.js
中,我在Router
的getUserConfirmation
中设置了对话框:
import { MemoryRouter as Router } from 'react-router-dom'
import { Modal } from 'antd'
import App from './App'
const { confirm } = Modal
const confirmNavigation = (message, callback) => {
confirm({
title: message,
onOk() {
callback(true)
},
onCancel() {
callback(false)
}
})
}
ReactDOM.render(
<Router getUserConfirmation={confirmNavigation}>
<App />
</Router>
document.getElementById('root')
)
然后,如果您尝试走开导航,则在其中使用要提示的组件,使用when
Prop提供一个条件以弹出模态。
import { Prompt } from 'react-router-dom'
class MyComponent extends React.Component {
render() {
return (
<div>
<Prompt
when={myDataHasNotSavedYet}
message="This will lose your changes. Are you sure want leave the page?"
/>
<RestOfMyComponent/>
</div>
)
}
}