I have a problem with react js and with setState in the documentation it says that it is asynchronous. And the problem I have is that I am using a Select and depending on the value that I select, it makes the request with ajax to the database, but since it is asynchronous, the value is not sent when clicking on an option the first time, but until the next. click on any option.
How do I send the updated value? I've seen that setState can take a second argument which is a callBack but I'm not sure how to update the value.
class HttpPeticion extends React.Component{
constructor(props){
super(props);
this.state={lista:[],
showData:false,showNodata:false,
cantidadResultados:'',
errorTipo:'',errorBool:false
};
}
handlerData(data){
if (typeof data=="undefined") return 0;
let errorTipo=data.tipo;
let errorBool=data.error;
if(errorBool){
this.setState({errorBool:data.error})
this.setState({errorTipo:data.tipo})
}
else{
let recordSize= data.records.length;
if(recordSize<= 0) {
this.setState({showData:false})//ocular resultados
this.setState({showNodata:true})//muestra "no hay datos"
}else{
this.setState({showData:true});//mostrar resultados
this.setState({showNodata:false})//ocultar "no hay datas"
this.setState({lista:data.records});
}
this.setState({cantidadResultados:recordSize + ' Coincidencias' });
}
}
componentWillReceiveProps(){
axios.post(this.props.urlServer,{'tipo':this.props.tipo,'nombre':this.props.nombre})
.then(res => {
this.handlerData(res.data.data);
})
.catch(function (error) {
console.log(error);
});
}
render(){
return (
<div>
<div>{this.state.cantidadResultados} </div>
<div className={this.state.showData ? '': 'hidden' }>
<ResultadoBusqueda datos={this.state.lista} />
</div>
<div className={this.state.showNodata ? '' : 'hidden'}>
<h1>No hay ningun resultado </h1>
</div>
<div className={this.state.errorBool ? '':'hidden'}>
<p>Un error ha ocurrido conectado con el ser servidor intente refresar la pagina(f5), si el problema
persiste contacte con el administrador.<a href="#">Mas informacion</a> </p>
<small>{this.state.errorTipo}</small>
</div>
</div>
);
}
}
class ResultadoBusqueda extends React.Component{
render(){
return(
<table>
<thead>
<tr>
<th>Cuenta</th>
<th>Nombre</th>
<th>Precio</th>
</tr>
</thead>
<tbody>
{
this.props.datos.map((item)=>{
return(
<tr key={item.cuenta.toString()}>
<td>{item.cuenta} </td>
<td>{item.nombre}</td>
</tr>
)
})
}
</tbody>
</table>
);
}
}
class BusquedaAlumno extends React.Component {
setField (e) {
//this.checkInput(e.target.value);
this.setState({[e.target.name]: e.target.value})
}
render() {
return (
<div>
<input type="text"
onChange={(e)=>this.setField(e)}
onKeyUp={(e)=>this.setField(e)}
name="valor1"
/>
<select onChange={(e)=>this.setField(e)} value={this.state.value} name="combo">
<option value="-1">Selecciones</option>
<option value="1">1</option>
<option value="0">0</option>
</select>
<div>{this.state.valor1}</div>
<div>{this.state.combo}</div>
<HttpPeticion tipo={this.state.combo} nombre={this.state.valor1} urlServer={"http://localhost/viaLacteaQueryBusquedaId.php"} />
</div>
);
}
If it shows me the data but it has that little inconvenience with the select and the textbox
You have to realize that if something doesn't add up in your development, you're basically doing something wrong. You also have a set of bad practices that you are carrying out:
e.target.name
andname="valor1"
, establishes a single value for what will be the attributename
either in the state or by variablesinput
the from,select
you'll never know when you need to apply more logic to your eventsIn conclusion to your question and for the reasons that I have given you, I would write your component in this way more or less depending on your needs
setState
The class methodComponent
accepts a callback as a second parameter to be executed when the state has already been updated .In the callback you can put any logic that depends on the success of updating that state entry.
In addition to @JoseAPL's recommendations, there is a problem in the handler that updates the state, for each input or select that updates the state you are not really updating the state, you are replacing it completely so by doing this.
you are replacing all the state and leaving it only with the field that is updated at that moment, eliminating the previous field, the solution is to use React's Immutability Helpers .
First import the library
Then define your handler like this.
As a good practice, always use Immutability Helpers to mutate the state.