无法读取未定义的属性“map”

时间:2014-07-11 20:44:48

标签: reactjs

我正在关注reactjs教程,并且在将值从一个组件的状态传递到另一个组件时,我一直遇到问题。当执行CommentList组件中的map函数时,抛出错误'无法读取属性'map'of undefined'。从CommentBox传递到CommentList时会导致prop变为undefined的原因是什么?

  var CommentList = React.createClass({
    render: function() {
      var commentNodes = this.props.data.map(function (comment){
        return (
          <div>
            <h1>{comment.author} </h1>
          </div>
        );
      });
      return (
        <div className="commentList">
          {commentNodes}
        </div>
      );
    }
  });

  var CommentBox = React.createClass({
    getInitialState: function(){
      return {data: []};
    },
    getComments: function(){
      $.ajax({
        url: this.props.url,
        dataType: 'json',
        success: function(data){
          this.setState({data: data});
        }.bind(this),
        error: function(xhr, status, err){
          console.error(url, status, err.toString());
        }.bind(this)
      });
    },
    componentWillMount: function(){
      this.getComments()
    },
    render: function(){
      return (
        <div className="commentBox">
          {/*this.state.data.comments*/}
          {<CommentList data={this.state.data.comments}/>}
        </div>
      );
    }
  });

  React.renderComponent(
    <CommentBox url="comments.json" />,
    document.getElementById('content')
  );

8 个答案:

答案 0 :(得分:35)

首先,设置更安全的初始数据:

getInitialState : function() {
    return {data: {comments:[]}};
},

确保您的ajax数据。

如果您遵循上述两条说明,例如Demo.

,它应该可以使用

更新:你可以用条件语句包装.map块。

if (this.props.data) {
  var commentNodes = this.props.data.map(function (comment){
      return (
        <div>
          <h1>{comment.author}</h1>
        </div>
      );
  });
}

答案 1 :(得分:11)

我想你忘了改变

data={this.props.data}

data={this.state.data}

在CommentBox的render函数中。在我学习本教程时,我犯了同样的错误。因此整个渲染功能应该看起来像

render: function() {
  return (
    <div className="commentBox">
      <h1>Comments</h1>
      <CommentList data={this.state.data} />
      <CommentForm />
    </div>
  );
}

而不是

render: function() {
  return (
    <div className="commentBox">
      <h1>Comments</h1>
      <CommentList data={this.props.data} />
      <CommentForm />
    </div>
  );

答案 2 :(得分:7)

您需要在渲染之前放置数据

应该是这样的:

var data = [
  {author: "Pete Hunt", text: "This is one comment"},
  {author: "Jordan Walke", text: "This is *another* comment"}
];

React.render(
  <CommentBox data={data}/>,
  document.getElementById('content')
);

而不是:

React.render(
  <CommentBox data={data}/>,
  document.getElementById('content')
);

var data = [
  {author: "Pete Hunt", text: "This is one comment"},
  {author: "Jordan Walke", text: "This is *another* comment"}
];

答案 3 :(得分:1)

如果"Cannot read property 'map' of undefined"中有错误或没有props.data数组,将遇到错误"this.props.data"

更好的放置条件来检查数组,如

if(this.props.data){
this.props.data.map(........)
.....
}

答案 4 :(得分:0)

我考虑在taggon的答案下对这个问题发表评论,但是好吧,我觉得它对那些对细节感兴趣的人对此有更多的解释。

  

未捕获的TypeError:无法读取未定义的属性“值” ,严格来说是JavaScript错误。   
(请注意,值可以是任何值,但此问题的值是'map')

了解这一点至关重要,这样可以避免无休止的调试周期。
此错误很常见,尤其是如果刚开始使用JavaScript(及其库/框架)。
对于React,这与了解component lifecycle methods有很多关系。

// Follow this example to get the context
// Ignore any complexity, focus on how 'props' are passed down to children

import React, { useEffect } from 'react'

// Main component
const ShowList = () => {
  // Similar to componentDidMount and componentDidUpdate
  useEffect(() => {// dispatch call to fetch items, populate the redux-store})

  return <div><MyItems items={movies} /></div>
}

// other component
const MyItems = props =>
  <ul>
    {props.items.map((item, i) => <li key={i}>item</li>)}
  </ul>


/**
  The above code should work fine, except for one problem.
  When compiling <ShowList/>,
  React-DOM renders <MyItems> before useEffect (or componentDid...) is called.
  And since `items={movies}`, 'props.items' is 'undefined' at that point.
  Thus the error message 'Cannot read property map of undefined'
 */

作为解决此问题的一种方法,@ taggon提供了一种解决方案(请参阅第一个anwser或链接)。

  

解决方案:设置一个初始值/默认值。
在我们的示例中,我们可以通过声明一个items值来避免default被“未定义”。空数组。

  为什么??这允许React-DOM最初呈现一个空列表。
当执行useEffectcomponentDid...方法时,该组件将使用填充的项目列表。

// Let's update our 'other' component
// destructure the `items` and initialize it as an array

const MyItems = ({items = []}) =>
  <ul>
    {items.map((item, i) => <li key={i}>item</li>)}
  </ul>

答案 5 :(得分:0)

主要由于未找到数组而发生错误。只需检查您是否已映射到正确的数组即可。检查数组名称或声明。

答案 6 :(得分:0)

在我的情况下,当我尝试向Promise.all处理程序添加类型时会发生这种情况:

Promise.all([1,2]).then(([num1, num2]: [number, number])=> console.log('res', num1));

如果删除: [number, number],该错误消失了。

答案 7 :(得分:0)

这对我有用。如果我使用 props.worktyp.map,它会向我抛出地图未定义的错误。

//App.js
    const worktyp = [
          "Full-time",
          "casual",
          "part-time",
          "contract"
        ];
    
    function Main(props){
      return(
    <section>
      <p>This the main body</p>
      <ul style = {{textAlign:"left"}}>
        **{worktyp.map((work) => <li>{work}</li>)}**
      </ul>
    </section>
    
      );
        }
 function App() {
      return (
        <div className="App">
          <Header name="initial"/>
          **<Main work={worktyp}/>**
          <Foot year ={new Date().getFullYear()}/>
        </div>
      );
    }
//index.js
    ReactDOM.render(
     <App />,
      document.getElementById('root')
    );