React.JS问题与重装组件

时间:2018-06-15 01:51:38

标签: javascript reactjs dictionary components

我今天开始学习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;

显然我不能使用地图(或者我甚至不需要它)。

知道我做错了什么吗?有更好的方法吗?

1 个答案:

答案 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;