update subproperty single react property array reactjs

subproperty - setstate object reactjs



setState(...): solo puede actualizar un componente montado o montado. Esto generalmente significa que llamó a setState() en un componente desmontado. Este es un no-op (11)

  1. Cancele todas las operaciones asíncronas en componentWillUnmount
  2. Comprobar componente ya está desmontado cuando la llamada asincrónica establece setState ,
    dado que la bandera isMounted está en desuso

componentDidMount(prevProps, prevState, prevContext) { let [audioNode, songLen] = [this.refs.audio, List.length-1]; audioNode.addEventListener(''ended'', () => { this._endedPlay(songLen, () => { this._currSong(this.state.songIndex); this._Play(audioNode); }); }); audioNode.addEventListener(''timeupdate'', () => { let [remainTime, remainTimeMin, remainTimeSec, remainTimeInfo] = []; if(!isNaN(audioNode.duration)) { remainTime = audioNode.duration - audioNode.currentTime; remainTimeMin = parseInt(remainTime/60); // 剩余分 remainTimeSec = parseInt(remainTime%60); // 剩余秒 if(remainTimeSec < 10) { remainTimeSec = ''0''+remainTimeSec; } remainTimeInfo = remainTimeMin + '':'' + remainTimeSec; this.setState({''time'': remainTimeInfo}); } }); } componentWillUnmount () { let audio = this.refs.audio; audio.removeEventListener(''timeupdate''); audio.removeEventListener(''ended''); }

Error:

Advertencia: setState (...): solo puede actualizar un componente montado o montado. Esto generalmente significa que llamó a setState () en un componente desmontado. Este es un no-op. Verifique el código del componente indefinido.

EliminoEventListener ''finalizó'' en componentWillUnmount , pero no funciona. porque agrego this.setState({''time'': remainTimeInfo}); en componentDidMount .


Encontré este problema porque usé setState lugar de state en el constructor.

EJEMPLO

Cambiar el siguiente código incorrecto

constructor(props) { super(props); this.setState({ key: '''' }); }

a

constructor(props) { super(props); this.state = { key: '''' }; }


Me he enfrentado al mismo problema desde que actualicé la última versión de reacción. Resuelto como a continuación.

Mi código fue

async componentDidMount() { const { default: Component } = await importComponent(); Nprogress.done(); this.setState({ component: <Component {...this.props} /> }); }

Cambiado a

componentWillUnmount() { this.mounted = false; } async componentDidMount() { this.mounted = true; const { default: Component } = await importComponent(); if (this.mounted) { this.setState({ component: <Component {...this.props} /> }); } }


Muchas de las respuestas en este hilo captan el uso de referencias, pero creo que un buen ejemplo sería bueno. Dado que está operando en un nodo DOM real utilizando el detector de eventos y saliendo del contexto React, una referencia debe considerarse la solución estándar. Aquí hay un ejemplo completo:

class someComponent extends Component { constructor(props) { super(props) this.node = null } render() { return ( <div ref={node => { this.node = node }}>Content</div> ) } handleEvent(event) { if (this.node) { this.setState({...}) } } componentDidMount() { //as soon as render completes, the node will be registered. const handleEvent = this.handleEvent.bind(this) this.node.addEventListener(''click'', handleEvent) } componentWillUnmount() { const handleEvent = this.handleEvent.bind(this) this.node.removeEventListener(''click'', handleEvent) } }


Recibí esta advertencia cuando quería mostrar una ventana emergente (modal de arranque) en la devolución de llamada de éxito / fracaso de la solicitud de Ajax. Además, setState no funcionaba y mi modal emergente no se mostraba.

Abajo estaba mi situación.

<Component /> (Containing my Ajax function) <ChildComponent /> <GrandChildComponent /> (Containing my PopupModal, onSuccess callback)

Estaba llamando a la función ajax del componente desde el componente nieto pasando una devolución de llamada onSuccess (definida en el componente nieto) que estaba configurando el estado para mostrar modal emergente.

Lo cambié a ...

<Component /> (Containing my Ajax function, PopupModal) <ChildComponent /> <GrandChildComponent />

En su lugar, llamé a setState (onSuccess Callback) para mostrar el popup modal en el componente (ajax callback) y resolvió el problema.

En el segundo caso: el componente se procesó dos veces (había incluido bundle.js dos veces en html).


Resolví esto asignando una referencia al componente y luego verificando si la referencia existe antes de establecer el estado:

myMethod(){ if (this.refs.myRef) this.setState({myVar: true}); } render() { return ( <div ref="myRef"> {this.state.myVar} </div> ); }


Tener un método con nombre en lugar de la función anónima en la devolución de llamada de audioNode.addEventListener debería eliminar la advertencia de asunto:

componentDidMount(prevProps, prevState, prevContext) { let [audioNode, songLen] = [this.refs.audio, List.length-1]; audioNode.addEventListener(''ended'', () => { this._endedPlay(songLen, () => { this._currSong(this.state.songIndex); this._Play(audioNode); }); }); audioNode.addEventListener(''timeupdate'', this.callbackMethod ); } callBackMethod = () => { let [remainTime, remainTimeMin, remainTimeSec, remainTimeInfo] = []; if(!isNaN(audioNode.duration)) { remainTime = audioNode.duration - audioNode.currentTime; remainTimeMin = parseInt(remainTime/60); // 剩余分 remainTimeSec = parseInt(remainTime%60); // 剩余秒 if(remainTimeSec < 10) { remainTimeSec = ''0''+remainTimeSec; } remainTimeInfo = remainTimeMin + '':'' + remainTimeSec; this.setState({''time'': remainTimeInfo}); } }

Y sí, el método con nombre es necesario de todos modos porque removeEventListener no funcionará con devoluciones de llamadas anónimas, como se mencionó anteriormente varias veces.


Tuve este problema antes, y lo resolví de acuerdo con la página oficial de React isMounted es un Antipatrón .

Establezca un isMounted propiedad isMounted para que sea verdadero en componentDidMount , y actívelo como falso en componentWillUnmount . Cuando setState() en sus devoluciones de llamada, compruebe isMounted primero. Esto funciona para mi.

state = { isMounted: false } componentDidMount() { this.setState({isMounted: true}) } componentWillUnmount(){ this.setState({isMounted: false}) }

llamar de vuelta:

if (this.state.isMounted) { this.setState({''time'': remainTimeInfo});}


addEventListener y removeEventListener, la devolución de llamada no debe ser una clase interna anónima y deben tener los mismos parámetros


removeEventListener tiene la misma firma que addEventListener . Todos los argumentos deben ser exactamente los mismos para que elimine el oyente.

var onEnded = () => {}; audioNode.addEventListener(''ended'', onEnded, false); this.cleanup = () => { audioNode.removeEventListener(''ended'', onEnded, false); }

Y en componentWillUnmount llame a this.cleanup() .


Editar : isMounted está en desuso y probablemente se eliminará en versiones posteriores de React. Mira this y esto, isMounted es un antipatrón .

Como dice la advertencia, está llamando this.setState en un componente que se montó pero que desde entonces se ha desmontado.

Para asegurarse de que su código sea seguro, puede envolverlo

if (this.isMounted()) { this.setState({''time'': remainTimeInfo}); }

para garantizar que el componente todavía esté montado.