Tengo un componente simple a continuación llamado Idea :
import './Idea.css'; import { useState } from 'react'; import { useParams } from 'react-router-dom'; function Idea() { const { id } = useParams(); const [ test, setTest ] = useState(''); console.log('Idea rendered'); const handleChange = (event) => { setTest(event.target.value); }; return ( <form> <input onChange={handleChange} value={test}/> </form> ); }; export default Idea;
Cada instancia de este componente se representa mediante el enrutador de reacción a través del enrutamiento dinámico, como se muestra en el segundo componente de ruta a continuación:
function App() { return ( <Provider store={store}> <BrowserRouter> <main> <SideBar /> <section id='main-window'> <Routes> <Route exact path="/" element={ <Instructions /> } /> <Route path="/ideas/:id" element={ <Idea/> } /> </Routes> </section> </main> </BrowserRouter> </Provider> ); };
El problema se ilustra en este ejemplo: ¡Digamos que estoy en la ruta /ideas/1234 y su valor de entrada dice hola mundo! . Si cambio a la ruta /ideas/5678 , la entrada en esa ruta también dirá ¡hola mundo! aunque especifiqué el valor de entrada para decir lo contrario al renderizar. Si cambio el valor de entrada en la ruta /ideas/5678 , el valor de entrada en la ruta /input/1234 también cambiará. Inevitablemente, ambos tendrán el mismo valor como si fueran lo mismo, independientemente de la ruta. Esto comenzó a suceder cuando introduje el enlace useState en el componente Idea. Supongo que useState debería restablecer el valor de entrada cada vez que cambio una ruta, pero esto no parece suceder.
Aquí está la documentación para el useState
: https://reactjs.org/docs/hooks-state.html
Aquí está la parte importante para su caso:
¿Qué hace llamar a useState? Declara una “variable de estado”. ... Esta es una forma de "preservar" algunos valores entre las llamadas de función ... Normalmente, las variables "desaparecen" cuando la función sale, pero React conserva las variables de estado.
Entonces, al introducir el gancho useState en el componente Idea
, en realidad está conservando el valor de entrada. Si desea que se elimine en función de una determinada condición, como si el valor de id
de useParams
ha cambiado, consulte useEffect
hook. Tal vez hacer algo como:
useEffect(()=> { setTest(''); }, [id]);
Dada la ruta <Route path="/ideas/:id" element={<Idea />} />
cuando el id
del parámetro de la ruta de la ruta cambia, el componente Route
no se desmonta ni monta una nueva instancia de Idea
, ya que esto sería un desperdicio, y en su lugar, simplemente volverá a representar Idea
con un nuevo parámetro de ruta de ruta proporcionado desde un contexto de enrutamiento.
Piense en esto como cualquier otro componente de React donde se vuelven a renderizar por una de estas tres razones:
Su código está en el tercer caso donde la ruta de la URL cambió y el componente Routes
coincide con el mejor componente Route
, y dado que <Route path="/ideas/:id" element={<Idea />} />
ya coincidía, se vuelve a representar , que vuelve a representar Idea
.
Si el componente enrutado necesita manejar cambios en los parámetros de la ruta, entonces debe usar el useEffect
para "escucharlos".
Ejemplo:
function Idea() { const { id } = useParams(); const [test, setTest] = useState(''); useEffect(() => { console.log('Idea rendered'); }); useEffect(() => { console.log('id updated', { id }); setTest(''); }, [id]); const handleChange = (event) => { setTest(event.target.value); }; return ( <form> <input onChange={handleChange} value={test} /> </form> ); };
Una alternativa a escuchar los cambios es crear un componente contenedor que use el parámetro de ruta como una clave React en el componente enrutado. El uso de este método desmontará y montará una nueva instancia de componente.
Ejemplo:
const IdeaWrapper = () => { const { id } = useParams(); return <Idea key={id} />; };
...
<Routes> <Route exact path="/" element={<Instructions />} /> <Route path="/ideas/:id" element={<IdeaWrapper />} /> </Routes>
Si lo desea, puede incluso crear un enlace de estado personalizado que se restablece en las actualizaciones de dependencia.
Ejemplo:
const useResetState = (initialState, deps) => { const [state, setState] = useState(initialState); useEffect(() => { setState(initialState); }, deps); return [state, setState]; };
...
function Idea() { const { id } = useParams(); const [test, setTest] = useResetState('', [id]); // <-- resets when id updates useEffect(() => { console.log('Idea rendered'); }); const handleChange = (event) => { setTest(event.target.value); }; return ( <form> <input onChange={handleChange} value={test} /> </form> ); };