Estoy escribiendo un script que mueve el menú desplegable por debajo o por encima 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 usar setStatedentro de la componentDidUpdatecrea un bucle infinito (que es obvio)
He encontrado una solución al usar getDOMNodey configurar classname para desplegable directamente, pero creo 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>
        );
    }
});
fuente

setStatehabrá siempre desencadenar una re-render. En lugar de verificarstate.topy llamarsetStatevarias veces, solo haga un seguimiento de lo que deseastate.topque esté en una variable local, luego una vez al final de lacomponentDidUpdatellamadasetStatesolo si su variable local no coincidestate.top. Tal como está ahora, reinicia inmediatamentestate.topdespués del primer renderizado, lo que lo coloca en el ciclo infinito.componentDidUpdateen este violín .componentShouldUpdate?Respuestas:
Puedes usar
setStatedentrocomponentDidUpdate. El problema es que de alguna manera estás creando un ciclo infinito porque no hay condición de ruptura.Según el hecho de que necesita valores proporcionados por el navegador una vez que se procesa el componente, creo que su enfoque sobre el uso
componentDidUpdatees correcto, solo necesita un mejor manejo de la condición que desencadena elsetState.fuente
componentDidUpdatey solo se puede agregar según sea necesariorender.La
componentDidUpdatefirma esvoid::componentDidUpdate(previousProps, previousState). Con esto podrás probar qué accesorios / estado están sucios y llamar ensetStateconsecuencia.Ejemplo:
fuente
componentDidMountno tiene ningún argumento, y solo se llama cuando se crea el componente, por lo que no se puede usar para el propósito descrito.componentDidMount, así que cuando escribí la respuesta el famoso nombre cayó en cascada 😮 Nuevamente, ¡Gracias y genial ponerse al día!componentDidUpdate(prevProps, prevState) { if ( prevState.x!== this.state.x) { //Do Something } }Si lo usa
setStatedentrocomponentDidUpdate, actualiza el componente, lo que resulta en una llamada a lacomponentDidUpdateque posteriormentesetStatevuelve a llamar, lo que resulta en un bucle infinito. Debe llamar condicionalmentesetStatey asegurarse de que la condición que viola la llamada ocurra eventualmente, por ejemplo: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
setStateinside encomponentWillReceivePropslugar decomponentDidUpdate.fuente
getDerivedStateFromProps.Este ejemplo lo ayudará a comprender los ganchos del ciclo de vida de React .
Puede
setStateengetDerivedStateFromPropsel método es decir,staticy desencadenar el método después de apoyos cambian encomponentDidUpdate.En
componentDidUpdateobtendrá 3er parámetro que regresa degetSnapshotBeforeUpdate.Puedes consultar este enlace de códigos y casillas
fuente
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í:
fuente
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
fuente