javascript - 重新加载组件的 React.JS 问题

标签 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;

显然我不能使用 map (或者我什至不需要它)。

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

最佳答案

此行为的原因是因为您使用来自服务器的响应重置整个状态,而不是更新特定的键值对。

初始状态

state = {lista : [], nome:'', email: '', senha: ''};

组件挂载后

state = { lista : [...] }

关于改变senha

state = { nome  : '...' }

因此,当 change 事件被触发时,没有要映射的 lista,因此您遇到了问题。

确保您保持现有状态不变,并仅覆盖您期望的 key

更新代码段

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;

关于javascript - 重新加载组件的 React.JS 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50868169/

相关文章:

javascript - fs 读取文件位置(如果已位于文件末尾)

javascript - Reactjs 监听滚动结束事件

python - 区分嵌套字典赋值和 Python 字典中的列表值访问

javascript - 如何在 slider 中显示六个产品?

javascript - 如何将循环变量传递给元素

node.js - 为什么我可以构建我的 React 应用程序但无法启动它

javascript - 如何在此选择菜单示例中使用 Reactjs 事件处理程序而不是 jQuery 事件处理程序?

python - 通过Python将csv文件转换为numpy数组

python 如何查找一个字典是否包含其他字典中的数据

javascript - 具有相同配置的两个 Chartjs 图表类型的 x 刻度未对齐 - 唯一的区别是 "chart type"(条形图/折线图)