我今天开始学习React,我在重新加载组件时遇到了问题。
应用程序非常简单,有一个API注册表单和一个从同一API中检索数据的表。
一切进展顺利,但现在当我提交表单时,我收到此消息(如果我重新加载页面,记录已经存在,那么api没有问题):
TypeError: this.state.lista.map is not a function
App.render
src/App.js:116
113 | </thead>
114 | <tbody>
115 | {
> 116 | this.state.lista.map(function(autor) {
117 | return (
118 | <tr key={autor.id}>
119 | <td>{autor.nome}</td>
这是我的App.js:
import React, { Component } from 'react';
import './css/pure-min.css';
import './css/side-menu.css';
import './css/main.css';
import $ from 'jquery';
class App extends Component {
constructor() {
super();
this.state = {lista : [], nome:'', email: '', senha: ''};
this.cadastraAutor = this.cadastraAutor.bind(this);
this.setNome = this.setNome.bind(this);
this.setEmail = this.setEmail.bind(this);
this.setSenha = this.setSenha.bind(this);
}
componentDidMount() {
$.ajax({
url: "http://localhost:8080/api/autores",
dataType: "json",
success: function(response) {
this.setState({lista:response});
}.bind(this)
});
}
cadastraAutor(event) {
event.preventDefault();
$.ajax({
url: "http://localhost:8080/api/autores",
contentType: "application/json",
dataType: "json",
type: "post",
data: JSON.stringify({
nome: this.state.nome,
email: this.state.email,
senha: this.state.senha
}),
success: function(response) {
this.setState({lista:response});
}.bind(this),
error: function(response) {
console.log('Erro');
}
});
}
setNome(event) {
this.setState({nome:event.target.value});
}
setEmail(event) {
this.setState({email:event.target.value});
}
setSenha(event) {
this.setState({senha:event.target.value});
}
render() {
return (
<div id="layout">
<a href="#menu" id="menuLink" className="menu-link">
<span></span>
</a>
<div id="menu">
<div className="pure-menu">
<a className="pure-menu-heading" href="">Company</a>
<ul className="pure-menu-list">
<li className="pure-menu-item"><a href="" className="pure-menu-link">Home</a></li>
<li className="pure-menu-item"><a href="" className="pure-menu-link">Autores</a></li>
<li className="pure-menu-item"><a href="" className="pure-menu-link">Livros</a></li>
</ul>
</div>
</div>
<div id="main">
<div className="header">
<h1>Cadastro de Autores</h1>
</div>
<div className="content top-spacing" id="content">
<div className="pure-form pure-form-aligned">
<form className="pure-form pure-form-aligned" onSubmit={this.cadastraAutor} method="post">
<div className="pure-control-group">
<label htmlFor="nome">Nome</label>
<input id="nome" type="text" name="nome" value={this.state.nome} onChange={this.setNome}/>
</div>
<div className="pure-control-group">
<label htmlFor="email">E-mail</label>
<input id="email" type="email" name="email" value={this.state.email} onChange={this.setEmail}/>
</div>
<div className="pure-control-group">
<label htmlFor="senha">Senha</label>
<input id="senha" type="password" name={this.state.senha} onChange={this.setSenha}/>
</div>
<div className="pure-control-group">
<label></label>
<button type="submit" className="pure-button pure-button-primary">Gravar</button>
</div>
</form>
</div>
<div>
<table className="pure-table">
<thead>
<tr>
<th>Nome</th>
<th>E-mail</th>
</tr>
</thead>
<tbody>
{
this.state.lista.map(function(autor) {
return (
<tr key={autor.id}>
<td>{autor.nome}</td>
<td>{autor.email}</td>
</tr>
);
})
}
</tbody>
</table>
</div>
</div>
</div>
</div>
);
}
}
export default App;
显然我不能使用地图(或者我甚至不需要它)。
知道我做错了什么吗?有更好的方法吗?
答案 0 :(得分:1)
行为的原因是因为您是服务器的resetting the entire state with the response
,而不是更新特定的键值对。
初始状态
state = {lista : [], nome:'', email: '', senha: ''};
组件安装后
state = { lista : [...] }
On change senha
state = { nome : '...' }
因此,当change
事件被触发时,没有映射lista
,因为您遇到了问题。
确保您保持现有状态不变,只需覆盖您期望的密钥
更新代码段
class App extends Component {
constructor() {
super();
this.state = {lista : [], nome:'', email: '', senha: ''};
this.cadastraAutor = this.cadastraAutor.bind(this);
this.setNome = this.setNome.bind(this);
this.setEmail = this.setEmail.bind(this);
this.setSenha = this.setSenha.bind(this);
this.updateState = this.updateState.bind(this);
}
componentDidMount() {
$.ajax({
url: "http://localhost:8080/api/autores",
dataType: "json",
success: function(response) {
this.setState({ lista: response });
}.bind(this)
});
}
updateState(response) {
Object.assign({}, this.state, response);
}
cadastraAutor(event) {
event.preventDefault();
$.ajax({
url: "http://localhost:8080/api/autores",
contentType: "application/json",
dataType: "json",
type: "post",
data: JSON.stringify({
nome: this.state.nome,
email: this.state.email,
senha: this.state.senha
}),
success: function(response) {
updateState({lista:response});
}.bind(this),
error: function(response) {
console.log('Erro');
}
});
}
setNome(event) {
updateState({ nome: event.target.value });
}
setEmail(event) {
updateState({ email: event.target.value });
}
setSenha(event) {
updateState({ senha: event.target.value });
}
render() {
return (
<div id="layout">
<a href="#menu" id="menuLink" className="menu-link">
<span></span>
</a>
<div id="menu">
<div className="pure-menu">
<a className="pure-menu-heading" href="">Company</a>
<ul className="pure-menu-list">
<li className="pure-menu-item"><a href="" className="pure-menu-link">Home</a></li>
<li className="pure-menu-item"><a href="" className="pure-menu-link">Autores</a></li>
<li className="pure-menu-item"><a href="" className="pure-menu-link">Livros</a></li>
</ul>
</div>
</div>
<div id="main">
<div className="header">
<h1>Cadastro de Autores</h1>
</div>
<div className="content top-spacing" id="content">
<div className="pure-form pure-form-aligned">
<form className="pure-form pure-form-aligned" onSubmit={this.cadastraAutor} method="post">
<div className="pure-control-group">
<label htmlFor="nome">Nome</label>
<input id="nome" type="text" name="nome" value={this.state.nome} onChange={this.setNome}/>
</div>
<div className="pure-control-group">
<label htmlFor="email">E-mail</label>
<input id="email" type="email" name="email" value={this.state.email} onChange={this.setEmail}/>
</div>
<div className="pure-control-group">
<label htmlFor="senha">Senha</label>
<input id="senha" type="password" name={this.state.senha} onChange={this.setSenha}/>
</div>
<div className="pure-control-group">
<label></label>
<button type="submit" className="pure-button pure-button-primary">Gravar</button>
</div>
</form>
</div>
<div>
<table className="pure-table">
<thead>
<tr>
<th>Nome</th>
<th>E-mail</th>
</tr>
</thead>
<tbody>
{
this.state.lista.map(function(autor) {
return (
<tr key={autor.id}>
<td>{autor.nome}</td>
<td>{autor.email}</td>
</tr>
);
})
}
</tbody>
</table>
</div>
</div>
</div>
</div>
);
}
}
export default App;