javascript - react - setstate component did update
setState() dentro de componentDidUpdate() (5)
Diría que debe verificar si el estado ya tiene el mismo valor que está tratando de establecer. Si es lo mismo, no tiene sentido volver a establecer el estado para el mismo valor.
Asegúrese de configurar su estado así:
let top = newValue /*true or false*/
if(top !== this.state.top){
this.setState({top});
}
Estoy escribiendo un script que mueve el menú desplegable debajo o arriba de la entrada, dependiendo de la altura del menú desplegable y la posición de la entrada en la pantalla.
También quiero configurar el modificador en el menú desplegable de acuerdo con su dirección.
Pero el uso de
setState
dentro del
componentDidUpdate
crea un bucle infinito (lo cual es obvio)
He encontrado una solución al usar
getDOMNode
y al configurar classname en el menú desplegable directamente, pero
getDOMNode
que debería haber una mejor solución usando las herramientas React.
Alguien puede ayudarme?
Aquí hay una parte del código de trabajo con
getDOMNode
(una lógica de posicionamiento un poco descuidada para simplificar el código)
let SearchDropdown = React.createClass({
componentDidUpdate(params) {
let el = this.getDOMNode();
el.classList.remove(''dropDown-top'');
if(needToMoveOnTop(el)) {
el.top = newTopValue;
el.right = newRightValue;
el.classList.add(''dropDown-top'');
}
},
render() {
let dataFeed = this.props.dataFeed;
return (
<DropDown >
{dataFeed.map((data, i) => {
return (<DropDownRow key={response.symbol} data={data}/>);
})}
</DropDown>
);
}
});
y aquí hay código con setstate (que crea un bucle infinito)
let SearchDropdown = React.createClass({
getInitialState() {
return {
top: false
};
},
componentDidUpdate(params) {
let el = this.getDOMNode();
if (this.state.top) {
this.setState({top: false});
}
if(needToMoveOnTop(el)) {
el.top = newTopValue;
el.right = newRightValue;
if (!this.state.top) {
this.setState({top: true});
}
}
},
render() {
let dataFeed = this.props.dataFeed;
let class = cx({''dropDown-top'' : this.state.top});
return (
<DropDown className={class} >
{dataFeed.map((data, i) => {
return (<DropDownRow key={response.symbol} data={data}/>);
})}
</DropDown>
);
}
});
La firma
componentDidUpdate
es
void::componentDidUpdate(previousProps, previousState)
.
Con esto podrás probar qué accesorios / estado están sucios y llamar a
setState
consecuencia.
Ejemplo:
componentDidUpdate(previousProps, previousState) {
if (previousProps.data !== this.props.data) {
this.setState({/*....*/})
}
}
Puede usar
setState
dentro de
componentDidUpdate
.
El problema es que de alguna manera estás creando un bucle infinito porque no hay condición de interrupción.
Según el hecho de que necesita valores proporcionados por el navegador una vez que se representa el componente, creo que su enfoque sobre el uso de
componentDidUpdate
es correcto, solo necesita un mejor manejo de la condición que desencadena el
setState
.
Si usa
setState
dentro de
componentDidUpdate
, actualiza el componente, lo que resulta en una llamada a
componentDidUpdate
que posteriormente llama a
setState
nuevamente y da como resultado el bucle infinito.
Debería llamar condicionalmente a
setState
y asegurarse de que la condición que viola la llamada ocurra eventualmente, por ejemplo:
componentDidUpdate: function() {
if (condition) {
this.setState({..})
} else {
//do something else
}
}
En caso de que solo esté actualizando el componente enviándole accesorios (no lo está actualizando setState, a excepción del caso dentro de componentDidUpdate), puede llamar a
setState
dentro de
componentWillReceiveProps
lugar de
componentDidUpdate
.
Tuve un problema similar en el que tengo que centrar la información sobre herramientas. React setState en componentDidUpdate me puso en bucle infinito, traté de que funcionara. Pero descubrí que usar la devolución de llamada de referencia me dio una solución más simple y limpia, si usa la función en línea para la devolución de llamada de referencia, se enfrentará al problema nulo para cada actualización de componentes. Por lo tanto, use la referencia de función en la devolución de llamada de referencia y establezca el estado allí, que iniciará el renderizado