記事Confirming Navigationは、トランジションフックでブラウザの確認ボックスを使用する方法を説明しています。ファイン。しかし、私は自分自身のダイアログボックスを使いたいです。私がhistory
モジュールのメソッドを使用するなら、これは可能だと思います。反応ルータのsetRouteLeaveHook
でこれを行うことは可能ですか?反応ルータのルートトランジションでカスタムコンポーネントを使用するにはどうすればいいですか?
答えて
setRouteLeaveHook
は、結果がと同時にのフック関数が返すことを期待しています。つまり、カスタムダイアログコンポーネントを表示する時間がなく、ユーザーがオプションをクリックするのを待ってから、、次にが結果を返します。したがって、非同期フックを指定する方法が必要です。ここで私が書いたユーティリティ関数です:
componentWillMount() {
setAsyncRouteLeaveHook(this.context.router, this.props.route, this.routerWillLeave)
}
routerWillLeave() {
return new Promise((resolve, reject) => {
if (!this.state.textValue) {
// No unsaved changes -- leave
resolve(true)
} else {
// Unsaved changes -- ask for confirmation
vex.dialog.confirm({
message: 'There are unsaved changes. Leave anyway?' + nextLocation,
callback: result => resolve(result)
})
}
})
}
Danielに感謝します。 setRouteLeaveHookがデフォルトのブラウザの確認ボックスを使用する場合、これは同期的に実行されると言っていますか? –
FYI、これはdialog/dialog polyfillでもうまくいきます。 –
解決してくれてありがとう、私は 'router.push(nextLocation)'がいつも動くかどうか疑問に思っていた。 「プッシュ」はただ一つの方向を示唆しているようだが、おそらく私は間違っている。 – majorBummer
上記は、ユーザーが履歴に戻ったときを除いて素晴らしいです:
ここ// Asynchronous version of `setRouteLeaveHook`.
// Instead of synchronously returning a result, the hook is expected to
// return a promise.
function setAsyncRouteLeaveHook(router, route, hook) {
let withinHook = false
let finalResult = undefined
let finalResultSet = false
router.setRouteLeaveHook(route, nextLocation => {
withinHook = true
if (!finalResultSet) {
hook(nextLocation).then(result => {
finalResult = result
finalResultSet = true
if (!withinHook && nextLocation) {
// Re-schedule the navigation
router.push(nextLocation)
}
})
}
let result = finalResultSet ? finalResult : false
withinHook = false
finalResult = undefined
finalResultSet = false
return result
})
}
は、ダイアログボックスを表示するvexを使用して、それを使用する方法の例です。次のようなものが問題を解決するはずです:
私の解決方法は同じです。私はあなたのアプリで任意のコンポーネントをラップするために使用できるカスタムダイアログコンポーネントを作った。ヘッダーをラップして、この方法ですべてのページに表示させることができます。 Reduxフォームを使用していることを前提としていますが、areThereUnsavedChanges
を他のフォームチェンジチェックコードに置き換えることができます。それはReact Bootstrapモーダルも使用します。これはあなた自身のカスタムダイアログで置き換えることができます。
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { withRouter, browserHistory } from 'react-router'
import { translate } from 'react-i18next'
import { Button, Modal, Row, Col } from 'react-bootstrap'
// have to use this global var, because setState does things at unpredictable times and dialog gets presented twice
let navConfirmed = false
@withRouter
@connect(
state => ({ form: state.form })
)
export default class UnsavedFormModal extends Component {
constructor(props) {
super(props)
this.areThereUnsavedChanges = this.areThereUnsavedChanges.bind(this)
this.state = ({ unsavedFormDialog: false })
}
areThereUnsavedChanges() {
return this.props.form && Object.values(this.props.form).length > 0 &&
Object.values(this.props.form)
.findIndex(frm => (Object.values(frm)
.findIndex(field => field && field.initial && field.initial !== field.value) !== -1)) !== -1
}
render() {
const moveForward =() => {
this.setState({ unsavedFormDialog: false })
navConfirmed = true
browserHistory.push(this.state.nextLocation.pathname)
}
const onHide =() => this.setState({ unsavedFormDialog: false })
if (this.areThereUnsavedChanges() && this.props.router && this.props.routes && this.props.routes.length > 0) {
this.props.router.setRouteLeaveHook(this.props.routes[this.props.routes.length - 1], (nextLocation) => {
if (navConfirmed || !this.areThereUnsavedChanges()) {
navConfirmed = false
return true
} else {
this.setState({ unsavedFormDialog: true, nextLocation: nextLocation })
return false
}
})
}
return (
<div>
{this.props.children}
<Modal show={this.state.unsavedFormDialog} onHide={onHide} bsSize="sm" aria-labelledby="contained-modal-title-md">
<Modal.Header>
<Modal.Title id="contained-modal-title-md">WARNING: unsaved changes</Modal.Title>
</Modal.Header>
<Modal.Body>
Are you sure you want to leave the page without saving changes to the form?
<Row>
<Col xs={6}><Button block onClick={onHide}>Cancel</Button></Col>
<Col xs={6}><Button block onClick={moveForward}>OK</Button></Col>
</Row>
</Modal.Body>
</Modal>
</div>
)
}
}
私は、(react-router 2.8.xを使用して)ナビゲートすることを確認したかどうかをブール値で設定しました。ただし、ユーザー
を促すW/O、彼らはフックが同様に未登録であることを言及するのを忘れての移行を防ぐために偽 https://github.com/ReactTraining/react-router/blob/master/docs/guides/ConfirmingNavigation.md
が復帰、:それはあなたが投稿リンクで言うようにhereおよびhereを参照してください。次のように
我々は独自のソリューションを実装するためにこれを使用することができます。
class YourComponent extends Component { constructor() { super(); const {route} = this.props; const {router} = this.context; this.onCancel = this.onCancel.bind(this); this.onConfirm = this.onConfirm.bind(this); this.unregisterLeaveHook = router.setRouteLeaveHook( route, this.routerWillLeave.bind(this) ); } componentWillUnmount() { this.unregisterLeaveHook(); } routerWillLeave() { const {hasConfirmed} = this.state; if (!hasConfirmed) { this.setState({showConfirmModal: true}); // Cancel route change return false; } // User has confirmed. Navigate away return true; } onCancel() { this.setState({showConfirmModal: false}); } onConfirm() { this.setState({hasConfirmed: true, showConfirmModal: true}, function() { this.context.router.goBack(); }.bind(this)); } render() { const {showConfirmModal} = this.state; return ( <ConfirmModal isOpen={showConfirmModal} onCancel={this.onCancel} onConfirm={this.onConfirm} /> ); } } YourComponent.contextTypes = { router: routerShape };
- 1. 反応ルータを使用してリダイレクトにパラメータを渡すにはどうすればよいですか?
- 2. 反応ルータのonEnterフックからreduxストアに接続するにはどうすればいいですか?
- 3. サーバレスアプリで反応ルータを動作させるにはどうすればいいですか?
- 4. 反応ルータv4で複数レベルのネスティングルートを管理するにはどうすればよいですか?
- 5. 反応ルータでアンカーを使用する
- 6. 反応ルータでRegexを使用する
- 7. 反応ルータのクリーンURLをIISに設定するにはどうすればよいですか?
- 8. ページリロード時に反応ルータのlocation.stateをクリアするにはどうすればよいですか?
- 9. 反応ルータでurlパラメータを検証するにはどうすればよいですか?
- 10. フォームを反応的にするにはどうすればいいですか?
- 11. divを反応的にするにはどうすればいいですか?
- 12. 反応ルータからコンポーネントの外部にあるURLパラメータをGraphQLクエリで使用するにはどうすればいいですか
- 13. 反応抑制剤の内部でd3.nestを使用するにはどうすればいいですか?
- 14. 反応ストーリーブックをどのように反応ストーリーブックで使用するにはどうすればいいですか?
- 15. 反応ルータv4との2つのルートのマッチングを防ぐにはどうすればよいですか?
- 16. リアクションネイティブルータフラックスでNavBarのタイトルとしてカスタムコンポーネントを使用するにはどうすればいいですか?
- 17. 反応ルータを使用する反応アプリでwindow.locationが機能しない4
- 18. 反応コンポーネントでjqueryスクリプトを使用するにはどうすればいいですか?
- 19. Expressルータと反応ルータを使用してGET/POSTリクエストを送信するにはどうすればよいですか?
- 20. デバイス上の反応するネイティブアプリケーションでchrome inspectを使用するにはどうすればよいですか?
- 21. 反応ルータを使用しているときに、親コンポーネントの状態を子コンポーネントから設定するにはどうすればよいですか?
- 22. riot.jsでルータを使用する際にライブラリを使用するにはどうすればよいですか?
- 23. 反応ルータv4のルート変更を聞くにはどうすればよいですか?
- 24. htmlテンプレートを反応させるにはどうすればいいですか?
- 25. ミックスインを反応させるにはどうすればいいですか?
- 26. 反応アプリでサードパーティの拡張機能を使用するにはどうすればよいですか?
- 27. 反応アプリでスタイル付きのコンポーネントを使用するにはどうすればよいですか?
- 28. 反応のvrでutf-8を使用するにはどうすればよいですか?
- 29. カスタムモジュール(Joomla 1.7)でカスタムコンポーネントの関数を使用するにはどうすればよいですか?
- 30. divを使用せずにiframeを反応的にするにはどうすればよいですか?
完全性について:これは履歴モジュールを使用するときにカスタムダイアログボックスを追加する方法を示したリンクです。 https://github.com/mjackson/history/blob/master/docs/ConfirmingNavigation.md –