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()
.
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()
.
Respuestas:
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.
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.
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 utilizado setState
, no se vuelve a mostrar
Actualizació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 un forceUpdate
:
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 regresan jsx
, no tiene acceso a los métodos del ciclo de vida de React ya que no se está extendiendo desde React.Component
.
Piense en el componente de función como la render
parte del método de los componentes de la clase.
props
o nuevos state
. no puede forzar la función de renderizado ya que no hay render
función en los componentes sin estado. Los componentes sin estado no extends
React.Component
son simplemente funciones que retornan jsx
.
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();
}
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} />;
};
useForceUpdate
use useCallback
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:
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>
)
}
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);