react prevstate getderivedstatefromprops example componentwillreceiveprops component reactjs constructor setstate

prevstate - ReactJS: Advertencia: setState(...): No se puede actualizar durante una transición de estado existente



setstate prevstate (8)

Estoy tratando de refactorizar el siguiente código desde mi vista de renderizado:

<Button href="#" active={!this.state.singleJourney} onClick={this.handleButtonChange.bind(this,false)} >Retour</Button>

a una versión donde el enlace está dentro del constructor. La razón de esto es que el enlace en la vista de renderizado me dará problemas de rendimiento, especialmente en teléfonos móviles de gama baja.

He creado el siguiente código, pero constantemente recibo los siguientes errores (muchos de ellos). Parece que la aplicación entra en un bucle:

Warning: setState(...): Cannot update during an existing state transition (such as within `render` or another component''s constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.

A continuación se muestra el código que uso:

var React = require(''react''); var ButtonGroup = require(''react-bootstrap/lib/ButtonGroup''); var Button = require(''react-bootstrap/lib/Button''); var Form = require(''react-bootstrap/lib/Form''); var FormGroup = require(''react-bootstrap/lib/FormGroup''); var Well = require(''react-bootstrap/lib/Well''); export default class Search extends React.Component { constructor() { super(); this.state = { singleJourney: false }; this.handleButtonChange = this.handleButtonChange.bind(this); } handleButtonChange(value) { this.setState({ singleJourney: value }); } render() { return ( <Form> <Well style={wellStyle}> <FormGroup className="text-center"> <ButtonGroup> <Button href="#" active={!this.state.singleJourney} onClick={this.handleButtonChange(false)} >Retour</Button> <Button href="#" active={this.state.singleJourney} onClick={this.handleButtonChange(true)} >Single Journey</Button> </ButtonGroup> </FormGroup> </Well> </Form> ); } } module.exports = Search;



El problema es sin duda este enlace mientras se desgarra el botón con el controlador onClick. La solución es utilizar la función de flecha al llamar al controlador de acciones mientras se procesa. De esta manera: onClick={ () => this.handleButtonChange(false) }


Esta misma advertencia se emitirá en cualquier cambio de estado realizado en una llamada render() .

Un ejemplo de un caso difícil de encontrar: cuando se procesa un componente de GUI de selección múltiple basado en datos de estado, si el estado no tiene nada que mostrar, una llamada a resetOptions() se considera un cambio de estado para ese componente.

La solución obvia es hacer resetOptions() en componentDidUpdate() lugar de render() .


Estoy dando un ejemplo genérico para una mejor comprensión, en el siguiente código

render(){ return( <div> <h3>Simple Counter</h3> <Counter value={this.props.counter} onIncrement={this.props.increment()} <------ calling the function onDecrement={this.props.decrement()} <----------- onIncrementAsync={this.props.incrementAsync()} /> </div> ) }

Al proporcionar accesorios, llamo a la función directamente, este wold tiene una ejecución de bucle infinito y le daría ese error. Elimine la función de llamada, todo funciona normalmente.

render(){ return( <div> <h3>Simple Counter</h3> <Counter value={this.props.counter} onIncrement={this.props.increment} <------ function call removed onDecrement={this.props.decrement} <----------- onIncrementAsync={this.props.incrementAsync} /> </div> ) }


La solución que uso para abrir Popover para componentes es reactstrap (React Bootstrap 4 components) .

class Settings extends Component { constructor(props) { super(props); this.state = { popoversOpen: [] // array open popovers } } // toggle my popovers togglePopoverHelp = (selected) => (e) => { const index = this.state.popoversOpen.indexOf(selected); if (index < 0) { this.state.popoversOpen.push(selected); } else { this.state.popoversOpen.splice(index, 1); } this.setState({ popoversOpen: [...this.state.popoversOpen] }); } render() { <div id="settings"> <button id="PopoverTimer" onClick={this.togglePopoverHelp(1)} className="btn btn-outline-danger" type="button">?</button> <Popover placement="left" isOpen={this.state.popoversOpen.includes(1)} target="PopoverTimer" toggle={this.togglePopoverHelp(1)}> <PopoverHeader>Header popover</PopoverHeader> <PopoverBody>Description popover</PopoverBody> </Popover> <button id="popoverRefresh" onClick={this.togglePopoverHelp(2)} className="btn btn-outline-danger" type="button">?</button> <Popover placement="left" isOpen={this.state.popoversOpen.includes(2)} target="popoverRefresh" toggle={this.togglePopoverHelp(2)}> <PopoverHeader>Header popover 2</PopoverHeader> <PopoverBody>Description popover2</PopoverBody> </Popover> </div> } }


Parece que accidentalmente estás llamando al método handleButtonChange en tu método de representación, probablemente quieras hacer onClick={() => this.handleButtonChange(false)} lugar.

Si no desea crear una lambda en el controlador onClick, creo que necesitará tener dos métodos enlazados, uno para cada parámetro.

En el constructor :

this.handleButtonChangeRetour = this.handleButtonChange.bind(this, true); this.handleButtonChangeSingle = this.handleButtonChange.bind(this, false);

Y en el método de render :

<Button href="#" active={!this.state.singleJourney} onClick={this.handleButtonChangeSingle} >Retour</Button> <Button href="#" active={this.state.singleJourney} onClick={this.handleButtonChangeRetour}>Single Journey</Button>


Recibí el mismo error cuando estaba llamando

this.handleClick = this.handleClick.bind(this);

en mi constructor cuando handleClick no existía

(Lo borré y accidentalmente dejé la declaración vinculante "this" en mi constructor).

Solución = eliminar la declaración vinculante "this".


Si está intentando agregar argumentos a un controlador en recompose , asegúrese de definir sus argumentos correctamente en el controlador. Es esencialmente una función currificada, por lo que debe asegurarse de requerir el número correcto de argumentos. Esta página tiene un buen ejemplo de uso de argumentos con manejadores.

Ejemplo (del enlace):

withHandlers({ handleClick: props => (value1, value2) => event => { console.log(event) alert(value1 + '' was clicked!'') props.doSomething(value2) }, })

para su hijo HOC y en el padre

class MyComponent extends Component { static propTypes = { handleClick: PropTypes.func, } render () { const {handleClick} = this.props return ( <div onClick={handleClick(value1, value2)} /> ) } }

Esto evita escribir una función anónima fuera de su controlador para corregir el problema al no proporcionar suficientes nombres de parámetros en su controlador.