繁体   English   中英

为什么 map function 在我的 React 应用程序中不起作用?

[英]Why the map function doesn't work in my React app?

我正在学习 React,我想构建一个如下所示的应用程序:

在此处输入图像描述

基本上,用户可以输入他的姓名和评论并发布。 发表的评论将显示在底部。 我正在使用 Tailwind CSS 来设置应用程序的样式。 下面是我的代码。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';


class MyName extends React.Component {
    render() {
        return (<div className="rounded border border-indigo-400 m-8 p-2">
            <div className="flex flex-col items-stretch space-y-2">
                <input type="text" placeholder="Who you are?" className="border border-gray-500" value={this.state.currentUser} onChange={(e) => {
                    this.setState({currentUser: e.target.value});
                }} />
                <textarea placeholder="Say something" className="h-32 border border-gray-500" value={this.state.currentData} onChange={(e) => {
                    this.setState({currentData: e.target.value});
                }}></textarea>
                <button className="bg-green-400 text-green-100 rounded py-1 hover:bg-green-600" onClick={() => {
                    if (this.state.currentUser && this.state.currentData) {
                        this.setState({
                            comments: this.state.comments.push({
                                user: this.state.currentUser,
                                data: this.state.currentData
                            })
                        });
                        this.state.currentUser = "";
                        this.state.currentData = "";
                    }
                }}>Post comment
                </button>
            </div>
            <div className="mt-8">
                {this.comments_section()}
            </div>
        </div>);
    }

    comments_section() {
        if (this.state.comments.length == 0) {
            return <span>No Comments.</span>
        }
        else {
            console.log(Array.isArray(this.state.comments));
            console.log(this.state.comments);
            return (<ul className="space-y-4">{this.state.comments.map((item) =>
                <li className="flex items-start space-x-2" key={item.user + item.data}>
                    <div className="flex flex-col items-start space-y-1">
                        <img className="rounded-full" src="http://placekitten.com/50/50" />
                        <span className="text-xs text-gray-500">{item.user}</span>
                    </div>
                    <span>{item.data}</span>
                </li>)}
            </ul>)
        }
    }

    constructor() {
        super();

        this.state = {
            currentUser: "",
            currentData: "",
            comments: [{
                user: "User One",
                data: "Hi, hello world!"
            }, {
                user: "User Two",
                data: "Hi, hello world!"
            }]
        }
    }
}

ReactDOM.render(
    <MyName />,
    document.getElementById('root')
);

reportWebVitals();

问题是,当我在输入中键入内容并单击按钮时,它会出错并指出this.state.comments.map不是 function。 我添加了一些console.log语句来调试它,发现起初this.state.comments是一个数组。 但是一旦我点击了按钮,它就不是了。 如何解决这个问题? 谢谢。

this.setState({
   comments: this.state.comments.push({
     user: this.state.currentUser,
     data: this.state.currentData
   })
});

array.push 返回一个数字,即数组的长度。 因此,您将 state.comments 设置为一个数字,而数字没有 map 方法。

您不应该为此使用 push,因为它会改变数组,并且 react 要求您的 state 是不可变的。 此外,您有几行手动设置 this.state.currentUser 和 this.state.currentData。 对 state 的更改应始终通过设置 state,而不是手动修改 this.state。

const newComments = [...this.state.comments, {
  user: this.state.currentUser,
  data: this.state.currentData
}]
this.setState({ 
  comments: newComments,
  currentUser: "",
  currentData: ""
});

另一个改进:由于您将新的 state 基于旧的 state,因此您应该使用 setState 的 function 版本。 React 将向您传递最新版本的 state,这消除了您使用过时版本的 state 的可能性(您的代码可能无法遇到此错误,但它可能发生在更复杂的情况下,所以它是好习惯)

this.setState(prev => {
  const newComments = [...prev.comments, {
    user: prev.currentUser,
    data: prev.currentData
  }]
  return { 
    comments: newComments
    currentUser: "",
    currentData: ""
  };
});

array.push返回一个数字,即数组的长度,因此您基本上是在将注释设置为其长度。

if (this.state.currentUser && this.state.currentData) {
  let { comments, currentUser, currentData } = this.state;
    comments.push({
     user: currentUser,
     data: currentData
    })
 this.setState({comments, currentUser : "", currentData: "" })
}

我不是反应专家,但我认为您需要像这样从 map 返回您的 jsx:

<ul className="space-y-4">
{this.state.comments.map((item) => return (
                <li className="flex items-start space-x-2" key={item.user + item.data}>
                    <div className="flex flex-col items-start space-y-1">
                        <img className="rounded-full" src="http://placekitten.com/50/50" />
                        <span className="text-xs text-gray-500">{item.user}</span>
                    </div>
                    <span>{item.data}</span>
                </li>))}
            </ul>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM