Chcę, aby moja aplikacja ReactJS powiadamiała użytkownika o opuszczeniu określonej strony. W szczególności wyskakująca wiadomość przypominająca mu o wykonaniu czynności:
„Zmiany zostały zapisane, ale nie zostały jeszcze opublikowane. Zrobić to teraz?”
Czy powinienem wywołać to react-router
globalnie, czy jest to coś, co można zrobić z poziomu strony / komponentu reagowania?
Nie znalazłem nic na temat tego ostatniego i wolałbym unikać pierwszego. Chyba że jest to norma, ale to sprawia, że zastanawiam się, jak zrobić coś takiego bez konieczności dodawania kodu do każdej innej możliwej strony, do której użytkownik może przejść.
Wszelkie spostrzeżenia mile widziane, dzięki!
reactjs
react-router
Barry Staes
źródło
źródło
componentWillUnmount() { if (confirm('Changes are saved, but not published yet. Do that now?')) { // publish and go away from a specific page } else { // do nothing and go away from a specific page } }
sposób, aby móc wywołać funkcję publikowania przed opuszczeniem stronyOdpowiedzi:
react-router
v4 wprowadza nowy sposób blokowania nawigacji przy użyciuPrompt
. Po prostu dodaj to do komponentu, który chcesz zablokować:Spowoduje to zablokowanie routingu, ale nie będzie odświeżania ani zamykania strony. Aby to zablokować, musisz to dodać (aktualizując w razie potrzeby z odpowiednim cyklem życia React):
onbeforeunload obsługuje różne przeglądarki.
źródło
onberforeunload
alert.react-router
nie obsługuje tego po wyjęciu z pudełka (zakładając, że przycisk anulowania nie powoduje żadnych zmian trasy). Możesz jednak stworzyć własny modal, aby naśladować to zachowanie.onbeforeunload
, będziesz chciał go wyczyścić po odłączeniu komponentu.componentWillUnmount() { window.onbeforeunload = null; }
W React-Router
v2.4.0
lub wyżej i wcześniejv4
jest kilka opcjionLeave
dlaRoute
setRouteLeaveHook
dlacomponentDidMount
Możesz zapobiec wystąpieniu przejścia lub monitować użytkownika przed opuszczeniem trasy za pomocą haka opuszczenia.
Należy zauważyć, że w tym przykładzie wykorzystano składnik
withRouter
wyższego rzędu wprowadzony wv2.4.0.
Jednak to rozwiązanie nie działa idealnie przy ręcznej zmianie trasy w adresie URL
W tym sensie
Aby
react-router v4
użyć Monit lub historii niestandardowej:Jednak
react-router v4
jest to raczej łatwiejsze do wdrożenia przy pomocyPrompt
speak-routerZgodnie z dokumentacją
W swojej metodzie renderowania wystarczy dodać to, jak wspomniano w dokumentacji, zgodnie z potrzebami.
AKTUALIZACJA:
W przypadku, gdy chciałbyś mieć niestandardową akcję do wykonania, gdy używasz opuszczania strony, możesz skorzystać z niestandardowej historii i skonfigurować router jak
history.js
a następnie w swoim komponencie możesz wykorzystać
history.block
podobneźródło
<Prompt>
adresu URL, zostanie zmieniony po naciśnięciu przycisku Anuluj w monicie. Powiązany problem: github.com/ReactTraining/react-router/issues/5405Dla
react-router
2.4.0+UWAGA : Zaleca się migrację całego kodu do najnowszej
react-router
aby uzyskać wszystkie nowe gadżety.Zgodnie z zaleceniami w dokumentacji reaktora routera :
Należy użyć
withRouter
komponentu wyższego rzędu:Jako przykład ES6 z dokumentacji:
źródło
W wersji
react-router
3.xMiałem ten sam problem, w którym potrzebowałem wiadomości z potwierdzeniem każdej niezapisanej zmiany na stronie. W moim przypadku korzystałem z React Router v3 , więc nie mogłem używać
<Prompt />
, który został wprowadzony z React Router v4 .Obsłużyłem „kliknięcie przycisku wstecz” i „przypadkowe kliknięcie linku” za pomocą kombinacji
setRouteLeaveHook
ihistory.pushState()
, a „przycisk przeładowania” obsłużyłem za pomocąonbeforeunload
obsługą zdarzeń.setRouteLeaveHook ( doc ) & history.pushState ( doc )
Używanie tylko setRouteLeaveHook nie wystarczyło. Z jakiegoś powodu adres URL został zmieniony, chociaż strona pozostała taka sama po kliknięciu przycisku „Wstecz”.
onbeforeunload ( doc )
Służy do obsługi przycisku „przypadkowego przeładowania”
Poniżej znajduje się pełny komponent, który napisałem
this.props.router
.this.props.route
jest przekazywana z komponentu wywołującegozauważ, że
currentState
jest przekazywany jako prop, aby mieć stan początkowy i sprawdzić wszelkie zmianyDaj mi znać, jeśli masz jakieś pytania :)
źródło
Dla
react-router
v0.13.x zreact
v0.13.x:jest to możliwe dzięki metodom
willTransitionTo()
iwillTransitionFrom()
statycznym. W przypadku nowszych wersji zobacz moją inną odpowiedź poniżej.Z dokumentacji reaktora routera :
Do
react-router
1.0.0-RC1 zreact
v0.14.x lub nowszej:powinno to być możliwe dzięki
routerWillLeave
haczykowi cyklu życia. W przypadku starszych wersji zobacz moją odpowiedź powyżej.Z dokumentacji reaktora routera :
Rzeczy. może się jednak zmienić przed ostatecznym wydaniem.
źródło
Możesz skorzystać z tego monitu.
źródło
Korzystanie z history.listen
Na przykład jak poniżej:
W Twoim komponencie
źródło