javascript - estado - react comunicacion entre componentes
¿Por qué llamar al método setState no muta el estado inmediatamente? (3)
Ok, intentaré hacerlo rápido porque DEBERÍA ser una solución fácil ...
He leído un montón de preguntas similares, y la respuesta parece ser bastante obvia. ¡Nada que tendría que buscar en primer lugar! Pero ... estoy teniendo un error que no puedo entender cómo solucionarlo o por qué está sucediendo.
Como sigue:
class NightlifeTypes extends Component {
constructor(props) {
super(props);
this.state = {
barClubLounge: false,
seeTheTown: true,
eventsEntertainment: true,
familyFriendlyOnly: false
}
this.handleOnChange = this.handleOnChange.bind(this);
}
handleOnChange = (event) => {
if(event.target.className == "barClubLounge") {
this.setState({barClubLounge: event.target.checked});
console.log(event.target.checked)
console.log(this.state.barClubLounge)
}
}
render() {
return (
<input className="barClubLounge" type=''checkbox'' onChange={this.handleOnChange} checked={this.state.barClubLounge}/>
)
}
Más código rodea esto, pero aquí es donde radica mi problema. Debería funcionar, ¿verdad?
También he intentado esto:
handleOnChange = (event) => {
if(event.target.className == "barClubLounge") {
this.setState({barClubLounge: !this.state.barClubLounge});
console.log(event.target.checked)
console.log(this.state.barClubLounge)
}
Entonces tengo esos dos
console.log()
, ambos deberían ser lo mismo.
¡Literalmente estoy configurando el estado para que sea el mismo que el
event.target.checked
en la línea por encima de él!
Pero siempre devuelve lo contrario de lo que debería.
Lo mismo ocurre cuando uso
!this.state.barClubLounge
;
¡Si comienza falso, en mi primer clic sigue siendo falso, incluso si la casilla de verificación está marcada o no se basa en el estado!
Es una paradoja loca y no tengo idea de lo que está pasando, ¡por favor ayuda!
Dado que setState es una función asíncrona. Eso significa que después de llamar a setState, la variable de estado no cambia inmediatamente. Entonces, si desea realizar otras acciones inmediatamente después de cambiar el estado, debe usar el método de devolución de llamada de setstate dentro de su función de actualización setState.
handleOnChange = (event) => {
let inputState = event.target.checked;
if(event.target.className == "barClubLounge") {
this.setState({ barClubLounge: inputState}, () => { //here
console.log(this.state.barClubLounge);
//here you can call other functions which use this state
variable //
});
}
}
Esto es por diseño debido a consideraciones de rendimiento. setState en React es una función garantizada para volver a representar Component, que es un proceso costoso de la CPU. Como tal, sus diseñadores querían optimizar mediante la recopilación de múltiples acciones de representación en una, por lo tanto, setState es asíncrono.
La razón es que
setState es asíncrono
, no puede esperar el valor de
state
actualizado justo después de
setState
, si desea verificar el valor use un método de
callback
.
Pase un método como devolución de llamada que se ejecutará después de que
setState
complete su tarea.
¿Por qué setState es asíncrono?
Esto se debe a que
setState
altera el
state
y provoca que se vuelva a
setState
.
Esta puede ser una operación costosa y hacerla
synchronous
puede dejar al navegador sin respuesta.
Por lo tanto, las llamadas a
setState
son
asynchronous
están
setState
para una mejor experiencia y rendimiento de la interfaz de usuario.
De Doc :
setState () no muta inmediatamente this.state pero crea una transición de estado pendiente. Acceder a this.state después de llamar a este método puede devolver el valor existente. No hay garantía de operación síncrona de llamadas a setState y las llamadas pueden ser agrupadas para obtener ganancias de rendimiento.
Usando el método de devolución de llamada con setState:
Para verificar el valor de
state
actualizado justo después de
setState
, use un método de devolución de llamada como este:
setState({ key: value }, () => {
console.log(''updated state value'', this.state.key)
})
Mira esto:
class NightlifeTypes extends React.Component {
constructor(props) {
super(props);
this.state = {
barClubLounge: false,
seeTheTown: true,
eventsEntertainment: true,
familyFriendlyOnly: false
}
}
handleOnChange = (event) => { // Arrow function binds `this`
let value = event.target.checked;
if(event.target.className == "barClubLounge") {
this.setState({ barClubLounge: value}, () => { //here
console.log(value);
console.log(this.state.barClubLounge);
//both will print same value
});
}
}
render() {
return (
<input className="barClubLounge" type=''checkbox'' onChange={this.handleOnChange} checked={this.state.barClubLounge}/>
)
}
}
ReactDOM.render(<NightlifeTypes/>, document.getElementById(''app''))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id=''app''/>