Tengo un componente de función y quiero forzarlo a volver a renderizar.
¿Como lo puedo hacer?
Como no hay instancia this
, no puedo llamar this.forceUpdate()
.
javascript
reactjs
Gorakh Nath
fuente
fuente
Respuestas:
🎉 Ahora puedes, usando React hooks
Usando react hooks, ahora puede llamar
useState()
a su componente de función.useState()
devolverá una matriz de 2 cosas:1. Un valor, que representa el estado actual.
2. Su armador. Úselo para actualizar el valor.
Actualizar el valor por su establecedor obligará a su componente de función a volver a renderizarse ,
al igual que lo
forceUpdate
hace:import React, { useState } from 'react'; //create your forceUpdate hook function useForceUpdate(){ const [value, setValue] = useState(0); // integer state return () => setValue(value => ++value); // update the state to force render } function MyComponent() { // call your hook here const forceUpdate = useForceUpdate(); return ( <div> {/*Clicking on the button will force to re-render like force update does */} <button onClick={forceUpdate}> Click to re-render </button> </div> ); }
Puede encontrar una demostración aquí .
El componente anterior usa una función de gancho personalizada (
useForceUpdate
) que usa un gancho de estado booleano (useState
). Cambia el estado booleano y, por lo tanto, le dice a React que vuelva a ejecutar la función de renderizado.EDITAR
En una versión anterior de esta respuesta, el fragmento usaba un valor booleano y lo alternaba
forceUpdate()
. Ahora que he editado mi respuesta, el fragmento usa un número en lugar de un booleano.Por qué ? (me preguntarías)
Porque una vez me sucedió que my
forceUpdate()
fue llamado dos veces posteriormente desde 2 eventos diferentes y, por lo tanto, se restableció el valor booleano en su estado original y el componente nunca se procesó.Porque en el
useState
setter de (setValue
aquí),React
compare el estado anterior con el nuevo y renderice solo si el estado es diferente.fuente
forceUpdate
.useState
gancho, no de la clase,setState
que de hecho no hace una comparación (a menos que implementes el método shouldUpdate). Vea la misma demostración que publiqué, pero con un valor estático utilizadosetState
, no se vuelve a mostrarActualización react v16.8 (versión 16 de febrero de 2019)
Dado que react 16.8 se lanzó con ganchos , los componentes de función ahora tienen la capacidad de mantener persistente
state
. Con esa habilidad ahora puedes imitar unforceUpdate
:Mostrar fragmento de código
function App() { const [, updateState] = React.useState(); const forceUpdate = React.useCallback(() => updateState({}), []); console.log("render"); return ( <div> <button onClick={forceUpdate}>Force Render</button> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script> <div id="root"/>
Tenga en cuenta que este enfoque debe reconsiderarse y, en la mayoría de los casos, cuando necesite forzar una actualización, probablemente esté haciendo algo mal.
Antes de reaccionar 16.8.0
No, no puede, los componentes de la función State-Less son simplemente normales
functions
que regresanjsx
, no tiene acceso a los métodos del ciclo de vida de React ya que no se está extendiendo desdeReact.Component
.Piense en el componente de función como la
render
parte del método de los componentes de la clase.fuente
props
o nuevosstate
. no puede forzar la función de renderizado ya que no hayrender
función en los componentes sin estado. Los componentes sin estado noextends
React.Component
son simplemente funciones que retornanjsx
.Preguntas frecuentes oficiales ( https://reactjs.org/docs/hooks-faq.html#is-there-something-like-forceupdate ) ahora recomienda de esta manera si realmente necesita hacerlo:
const [ignored, forceUpdate] = useReducer(x => x + 1, 0); function handleClick() { forceUpdate(); }
fuente
const [, forceUpdate] = useReducer(x => x + 1, 0);
Usé una biblioteca de terceros llamada use-force-update para forzar la representación de mis componentes funcionales de reacción. Funcionó a la perfección. Simplemente use importar el paquete en su proyecto y utilícelo así.
import useForceUpdate from 'use-force-update'; const MyButton = () => { const forceUpdate = useForceUpdate(); const handleClick = () => { alert('I will re-render now.'); forceUpdate(); }; return <button onClick={handleClick} />; };
fuente
useForceUpdate
useuseCallback
como se menciona en otras respuestas. Esta lib es solo una lib de utilidad para ahorrarle pocas pulsaciones de teclas.Descargo de responsabilidad: NO ES UNA RESPUESTA AL PROBLEMA.
Dejando una nota importante aquí:
Si está intentando forzar la actualización de un componente sin estado, es probable que haya algún problema con su diseño.
Considere los siguientes casos:
fuente
Esto se puede hacer sin usar explícitamente ganchos siempre que agregue un accesorio a su componente y un estado al componente principal del componente sin estado:
const ParentComponent = props => { const [updateNow, setUpdateNow] = useState(true) const updateFunc = () => { setUpdateNow(!updateNow) } const MyComponent = props => { return (<div> .... </div>) } const MyButtonComponent = props => { return (<div> <input type="button" onClick={props.updateFunc} />.... </div>) } return ( <div> <MyComponent updateMe={updateNow} /> <MyButtonComponent updateFunc={updateFunc}/> </div> ) }
fuente
La respuesta aceptada es buena. Solo para que sea más fácil de entender.
Componente de ejemplo:
export default function MyComponent(props) { const [updateView, setUpdateView] = useState(0); return ( <> <span style={{ display: "none" }}>{updateView}</span> </> ); }
Para forzar la re-renderización, llame al siguiente código:
setUpdateView((updateView) => ++updateView);
fuente