Estaba siguiendo una presentación de Ryan florence (creador de remix y ReactTraining.com). Allí estaba desmitificando el uso del gancho de estado, haciendo uno propio.
Seguí el procedimiento e implementé esto en un componente.
import React from 'react' import ReactDOM from 'react-dom'; function MadeUseStateMyself() { const [minutes,setMinutes] = useState(5) const [error,setError] = useState(null) const handleAdd = () => { if(minutes<9){ setMinutes(minutes+1) setError(null) } else{ setError('Less than 10 please') } } const handleSubStract = () => { if(minutes>0){ setMinutes(minutes-1) setError(null) } else{ setError('More than 0 please') } } return ( <React.Fragment> <button onClick={handleSubStract} > - </button> <p>{minutes}</p> <button onClick={handleAdd} > + </button> {error && <div>{error}</div>} </React.Fragment> ) } const states = [] let calls = -1 const useState = def => { const callId = ++calls if(states[callId]) { return states[callId] } const setDef = newV => { states[callId][0] = newV reRender() } const state = [def,setDef] states.push(state) return state } function reRender(){ calls = -1 ReactDOM.render(<MadeUseStateMyself/>,document.getElementById('root')) } export default MadeUseStateMyself Aquí noté un comportamiento realmente peculiar, es decir, cada vez que uso React.StrictMode envolviendo todo mi componente, el estado no cambia después de la primera llamada a la función (en este caso, implementé un botón incremental y decremental que cambia el estado de uno estado entero singular.)
Este problema no surge si me deshago del envoltorio React.StrictMode . Aquí hay un CodeSandbox
Al leer los documentos de StrictMode , una de mis suposiciones es que, como en modo estricto, los cuerpos de los componentes de función se invocan dos veces, pierde su primer estado durante la segunda llamada de función, por lo que pierde el primer cambio de estado.
¿Estoy siquiera cerca?
Tuve que mirar unos 13 minutos en el video para detectar la primera diferencia entre su código y el de la demostración. El presentador dijo que invoque manualmente de inmediato la función de reRender personalizado para hacer el renderizado inicial. Desde aquí me di cuenta de que estabas renderizando tu aplicación dos veces. MadeUseStateMyself se representa una vez en la función reRender personalizada y también se exporta y representa nuevamente en el DOM en el archivo index.js .
Efectivamente, tiene dos instancias de su componente MadeUseStateMyself representado como un React pisoteándose entre sí.
Si toma su código e inmediatamente invoca reRender , y también elimina por completo el código de renderizado index.js , mientras también envuelve MadeUseStateMyself en un componente React.StrictMode , verá que no tiene problemas para renderizar y actualizar.
HechoUsoEstadoYo mismo
import React from "react"; import ReactDOM from "react-dom"; const states = []; let calls = -1; const useState = (def) => { const callId = ++calls; if (states[callId]) { return states[callId]; } const setDef = (newV) => { states[callId][0] = newV; reRender(); }; const state = [def, setDef]; states.push(state); return state; }; function MadeUseStateMyself() { const [minutes, setMinutes] = useState(5); const [error, setError] = useState(null); const handleAdd = () => { if (minutes < 9) { setMinutes(minutes + 1); setError(null); } else { setError("Less than 10 please"); } }; const handleSubStract = () => { if (minutes > 0) { setMinutes(minutes - 1); setError(null); } else { setError("More than 0 please"); } }; return ( <React.Fragment> <button onClick={handleSubStract}> - </button> <p>{minutes}</p> <button onClick={handleAdd}> + </button> {error && <div>{error}</div>} </React.Fragment> ); } function reRender() { calls = -1; ReactDOM.render( <React.StrictMode> // <-- add the React.StrictMode <MadeUseStateMyself /> </React.StrictMode>, document.getElementById("root") ); } reRender(); // <-- Invoke immediately