错误:无法读取未定义的属性“地图”

IT技术 reactjs
2021-04-09 00:11:47

我正在学习reactjs教程,并且在
将值从一个组件的状态传递到另一个组件时一直遇到问题

执行组件中Cannot read property 'map' of undefined'map函数时抛出错误CommentList

什么会导致的propundefined从路过的时候CommentBoxCommentList

// First component
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>;
  }
});
// Second component    
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">{<CommentList data={this.state.data.comments}/>}</div>;
   }
});

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

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

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>
      );
  });
}
这个解决方案有效,但我很好奇。如果我有一个更复杂的 JSON 结构,我是否必须以相同的方式初始化数据对象?似乎应该有更好的方法。谢谢
2021-05-26 00:11:47
发生错误是因为this.props.data为空。.map期望在数组上调用。
2021-06-05 00:11:47
this.props.data由 AJAX 请求填充。AJAX 是异步的,因此如果在填充数据之前呈现组件,则该组件this.props.data将为 null,并且您将收到错误消息。这有意义吗?
2021-06-07 00:11:47
@Nael 不,你不需要。只需像上面一样包裹块。:)
2021-06-09 00:11:47
@timothyclifford 感谢您的回答。我知道this.props.data是 null 导致地图功能失败。但我不明白的是,教程代码在没有 if 子句的情况下也能工作。为什么this.props.data教程中不为空?
2021-06-21 00:11:47

我想你忘了改变

data={this.props.data}

data={this.state.data}

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

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

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

应该是这样的:

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"}
];

错误"Cannot read property 'map' of undefined",如果有在一个错误会遇到"this.props.data"或没有props.data阵列。

更好地放置条件来检查数组

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

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

未捕获的类型错误:无法读取未定义的属性“值”严格来说是 JavaScript 错误。
(请注意, value 可以是任何东西,但对于这个问题, value 是 'map')

理解这一点至关重要,这样您就可以避免无休止的调试循环。
这个错误很常见,特别是如果刚开始使用 JavaScript(和它的库/框架)。
因为React,这与理解组件生命周期方法有很大关系

// 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 最初呈现一个空列表。
并且当useEffectorcomponentDid...方法被执行时,组件会被重新渲染为一个填充的项目列表。

// 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>