简体   繁体   English

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

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

I'm learning React and I want to build an application that looks like this:我正在学习 React,我想构建一个如下所示的应用程序:

在此处输入图像描述

Basically the user can put his name and comment and post it.基本上,用户可以输入他的姓名和评论并发布。 The posted comments will be displayed in the bottom.发表的评论将显示在底部。 I'm using Tailwind CSS to style the app.我正在使用 Tailwind CSS 来设置应用程序的样式。 Below is my code.下面是我的代码。

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();

The problem is that when I type something in the inputs and click the button, it errors out and states this.state.comments.map is not a function.问题是,当我在输入中键入内容并单击按钮时,它会出错并指出this.state.comments.map不是 function。 I added some console.log statement to debug it and found that at first this.state.comments is an array.我添加了一些console.log语句来调试它,发现起初this.state.comments是一个数组。 But once I clicked the button, it is not.但是一旦我点击了按钮,它就不是了。 How to fix this issue?如何解决这个问题? Thanks.谢谢。

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

array.push returns a number, which is the length of the array. array.push 返回一个数字,即数组的长度。 So you're setting state.comments to a number, and numbers don't have a map method.因此,您将 state.comments 设置为一个数字,而数字没有 map 方法。

You shouldn't use push for this, since it mutates the array, and react requires your state to be immutable.您不应该为此使用 push,因为它会改变数组,并且 react 要求您的 state 是不可变的。 Additionally, you have a couple lines where you're manually setting this.state.currentUser and this.state.currentData.此外,您有几行手动设置 this.state.currentUser 和 this.state.currentData。 Changes to the state should always be through set state, not manual modification of this.state.对 state 的更改应始终通过设置 state,而不是手动修改 this.state。

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

An additional improvement: since you're basing your new state on your old state, you should use the function version of setState.另一个改进:由于您将新的 state 基于旧的 state,因此您应该使用 setState 的 function 版本。 React will pass you the most recent version of the state, which eliminates the possibility that you're using a stale version of the state (your code probably can't run into this bug, but it can happen in more complicated cases, so it's good to get in the habit) React 将向您传递最新版本的 state,这消除了您使用过时版本的 state 的可能性(您的代码可能无法遇到此错误,但它可能发生在更复杂的情况下,所以它是好习惯)

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

array.push returns a number ie length of the array so you are basically setting comments to its length. 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: "" })
}

I am not a react expert but I think you need to return your jsx from the map like this:我不是反应专家,但我认为您需要像这样从 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