javascript - single - setstate array react
Reaccionar this.setState no es una función (10)
Soy nuevo en React y estoy tratando de escribir una aplicación que funcione con una API. Sigo recibiendo este error:
TypeError: this.setState no es una función
cuando trato de manejar la respuesta API. Sospecho que hay algo mal con este enlace, pero no puedo encontrar la manera de solucionarlo. Aquí está el código de mi componente:
var AppMain = React.createClass({
getInitialState: function() {
return{
FirstName: " "
};
},
componentDidMount:function(){
VK.init(function(){
console.info("API initialisation successful");
VK.api(''users.get'',{fields: ''photo_50''},function(data){
if(data.response){
this.setState({ //the error happens here
FirstName: data.response[0].first_name
});
console.info(this.state.FirstName);
}
});
}, function(){
console.info("API initialisation failed");
}, ''5.34'');
},
render:function(){
return (
<div className="appMain">
<Header />
</div>
);
}
});
Ahora ES6 tiene función de flecha, es realmente útil si realmente confundes con la expresión bind (this) puedes probar la función de flecha
Así es como lo hago.
componentWillMount() {
ListApi.getList()
.then(JsonList => this.setState({ List: JsonList }));
}
//Above method equalent to this...
componentWillMount() {
ListApi.getList()
.then(function (JsonList) {
this.setState({ List: JsonList });
}.bind(this));
}
Ahora, en reaccionar con es6 / 7, puede vincular la función al contexto actual con la función de flecha como esta, hacer una solicitud y resolver promesas como esta:
listMovies = async () => {
const request = await VK.api(''users.get'',{fields: ''photo_50''});
const data = await request.json()
if (data) {
this.setState({movies: data})
}
}
Con este método, puede llamar fácilmente a esta función en el componenteDidMount y esperar los datos antes de representar su html en su función de representación.
No sé el tamaño de su proyecto, pero personalmente desaconsejo usar el estado actual del componente para manipular datos. Debe usar un estado externo como Redux o Flux o algo más para eso.
Aquí ESTE contexto está cambiando. Use la función de flecha para mantener el contexto de la clase React.
VK.init(() => {
console.info("API initialisation successful");
VK.api(''users.get'',{fields: ''photo_50''},(data) => {
if(data.response){
this.setState({ //the error happens here
FirstName: data.response[0].first_name
});
console.info(this.state.FirstName);
}
});
}, function(){
console.info("API initialisation failed");
}, ''5.34'');
La devolución de llamada se realiza en un contexto diferente.
Debe
bind
a
this
para tener acceso dentro de la devolución de llamada:
VK.api(''users.get'',{fields: ''photo_50''},function(data){
if(data.response){
this.setState({ //the error happens here
FirstName: data.response[0].first_name
});
console.info(this.state.FirstName);
}
}.bind(this));
EDITAR: Parece que tienes que vincular las llamadas
init
y
api
:
VK.init(function(){
console.info("API initialisation successful");
VK.api(''users.get'',{fields: ''photo_50''},function(data){
if(data.response){
this.setState({ //the error happens here
FirstName: data.response[0].first_name
});
console.info(this.state.FirstName);
}
}.bind(this));
}.bind(this), function(){
console.info("API initialisation failed");
}, ''5.34'');
No es necesario asignar esto a una variable local si utiliza la función de flecha. Las funciones de flecha se vinculan automáticamente y puede mantenerse alejado de los problemas relacionados con el alcance.
El siguiente código explica cómo usar la función de flecha en diferentes escenarios
componentDidMount = () => {
VK.init(() => {
console.info("API initialisation successful");
VK.api(''users.get'',{fields: ''photo_50''},(data) => {
if(data.response){
that.setState({ //this available here and you can do setState
FirstName: data.response[0].first_name
});
console.info(that.state.FirstName);
}
});
}, () => {
console.info("API initialisation failed");
}, ''5.34'');
},
Puede evitar la necesidad de .bind (esto) con una función de flecha ES6.
VK.api(''users.get'',{fields: ''photo_50''},(data) => {
if(data.response){
this.setState({ //the error happens here
FirstName: data.response[0].first_name
});
console.info(this.state.FirstName);
}
});
React recomienda vincular esto en todos los métodos que necesitan usar esto de
class
lugar de esto de auto
function
.
constructor(props) {
super(props)
this.onClick = this.onClick.bind(this)
}
onClick () {
this.setState({...})
}
O puede usar la
arrow function
lugar.
Si está haciendo esto y todavía tiene un problema, mi problema es que estaba llamando a dos variables con el mismo nombre.
Tenía
companies
como un objeto traído de Firebase, y luego estaba tratando de llamar a
this.setState({companies: companies})
, no estaba funcionando por razones obvias.
Solo necesitas vincular tu evento
por ex
// place this code to your constructor
this._handleDelete = this._handleDelete.bind(this);
// and your setState function will work perfectly
_handleDelete(id){
this.state.list.splice(id, 1);
this.setState({ list: this.state.list });
// this.setState({list: list});
}
También puede guardar una referencia a
this
antes de invocar el método
api
:
componentDidMount:function(){
var that = this;
VK.init(function(){
console.info("API initialisation successful");
VK.api(''users.get'',{fields: ''photo_50''},function(data){
if(data.response){
that.setState({ //the error happens here
FirstName: data.response[0].first_name
});
console.info(that.state.FirstName);
}
});
}, function(){
console.info("API initialisation failed");
}, ''5.34'');
},