Estoy trabajando en un spa de reacción para mostrar alertas sobre cambios de formulario no guardados. Estoy usando React-router-dom@5.2.0 Prompt Component para este caso de uso.
La página que tiene el formulario también tiene un iframe. El problema es cuando el usuario completa el formulario pero no lo guarda e intenta navegar usando el botón de retroceso del navegador, se muestra la alerta y si el usuario cancela la navegación, el iframe descarga/carga se activa aunque la página misma no se desmontó/montó. Esto lleva a que el iframe pierda su estado.
Esta respuesta es para react-router-dom v6
La solución de trabajo se coloca en el repositorio de Github .
Eche un vistazo al código principal, src/pages/Demo.tsx :
import Iframe from "react-iframe"; import React from "react"; import {usePrompt} from "../hooks/usePromptBlocker"; const Demo = () => { usePrompt( "Hello from usePrompt -- Are you sure you want to leave?", true ); return ( <Iframe url={'http://127.0.0.1:5500/demo-form.html'} width="375" height="667"/> ); } export default Demo;A veces revertiremos la versión de react-router-dom a v5 y no usaremos react-router-dom v6 porque usePrompt y useBlocker se han ido .
Definitivamente podemos usar v6 ahora, ya que se ha introducido una solución aquí .
Uso Prompt de react-router-dom combinado con un estado en la función onFocus
import React, { useRef, useState, Fragment } from "react"; import { Prompt } from "react-router-dom"; const QuoteForm = (props) => { const textInputRef = useRef(); // FOCUSED FORM STATE const [isEntering, setIsEntering] = useState(false); function submitFormHandler(event) { event.preventDefault(); const enteredText = textInputRef.current.value; } // LEAVING THE FORM PROMPT const doneEnteringHandler = () => { setIsEntering(false); }; const focusedForm = () => { setIsEntering(true); }; return ( <Fragment> <Prompt when={isEntering} message={(location) => "All data will be lost."} /> <Card> <form onFocus={focusedForm} className={classes.form} onSubmit={submitFormHandler} > <div> <label htmlFor="text">Text</label> <textarea id="text" rows="5" ref={textInputRef}></textarea> </div> <div> <button onClick={doneEnteringHandler} className="btn">Add Quote</button> </div> </form> </Card> </Fragment> ); }; export default QuoteForm;