简体   繁体   English

props.items.map不是使用React的函数

[英]props.items.map is not a function using React

I am using React as a beginner, and I looked up the error I was getting and most people say you cannot use map with an object, it must be an array. 我正在使用React作为初学者,我查找了我遇到的错误,大多数人说您不能将map与对象一起使用,它必须是数组。 But I am getting back the following data for my props.items when put in console.log: 但是当放到console.log中时,我正在获取有关props.items的以下数据:

[{
  ItemKey: 82521,
  ISBN: "158344422X",
  Title: "Butterflies And Moths",
  Publisher: "Benchmark Education",
  Illustrator: " "
}, {
  ItemKey: 85938,
  ISBN: "9780452274426",
  Title: "In the Time of the Butterflies",
  Publisher: "Penguin Plume",
  Illustrator: " "
}]

So it is returning an array. 因此它正在返回一个数组。 But I still get the map is not a function error. 但是我仍然得到映射不是函数错误。 Here is my code: 这是我的代码:

function ItemGrid (props){
    return (
        <ul className='items-list'>
            {props.items.map(function(item, index){
                <li key={item.Title} className="items-list-item">
                </li>
            })}
        </ul>
    )
}

Does anyone see anything unusual about the code I wrote or the object getting returned? 有人看到我编写的代码有异常或对象返回了吗?

EDIT: Here is how I am getting the data: 编辑:这是我如何获取数据:

module.exports = {
    fetchItems: function(){
        var encodedURI = window.encodeURI('http://localhost:8081/items?Title=butterflies', { crossdomain: true });
        return axios.get(encodedURI).then(function(response){
            return response.data;
        });
    }
}

And I am passing data to ItemGrid through: 我通过以下方式将数据传递给ItemGrid:

componentDidMount(){
    api.fetchItems().then(function(items){
        this.setState(function(){
            return {
                items: items
            }
        })
    }.bind(this));
}

render() {
    return (<div>
        <ItemGrid items={this.state.items} />
    </div>);
}

I am also having trouble getting the li items to show up once the data is present: 一旦数据存在,我也很难显示li项目:

<ul className='items-list'>

            {items && items.map(function (item, index) {
                console.log(item);
                <li key={index} className='items-list-item'>
                    item.Title
                </li>
            })}
        </ul>

The render function can and will be called several times, often without any data the first time through. 可以并且将多次调用render函数,通常在第一次使用时就没有任何数据。

So you need to check if your data is present before you try and iterate over it with the map() function. 因此,您需要先检查数据是否存在,然后再尝试使用map()函数对其进行迭代。

if props.items is not present you can return something simple like null or even "Loading", and the next time around (when the data is there) it will work as expected. 如果不存在props.items则可以返回简单的内容,例如null或什至是“ Loading”,并且下次(当数据存在时)它将按预期工作。

So your new code could be this (only rendering if props.items is defined): 因此,您的新代码可能是这样(仅在定义了props.items的情况下才呈现):

function ItemGrid (props){
    return (
        <ul className='items-list'>
            {props.items && props.items.map(function(item, index){
                <li key={item.Title} className="items-list-item">
                </li>
            })}
        </ul>
    )
}

The correct solution depends on how the data is being retrieved. 正确的解决方案取决于如何检索数据。 If it's a simple JS array within your script, the data should be available when the component is mounted. 如果它是脚本中的简单JS数组,那么在安装组件时,数据应该可用。

 var data = [{ ItemKey: 82521, ISBN: "158344422X", Title: "Butterflies And Moths", Publisher: "Benchmark Education", Illustrator: " " }, { ItemKey: 85938, ISBN: "9780452274426", Title: "In the Time of the Butterflies", Publisher: "Penguin Plume", Illustrator: " " }]; function ItemGrid(props) { var items = props.items; return ( <ul className='items-list'> { items.map(function(item, index) { return (<li key={item.ItemKey} className="items-list-item">{item.Title}</li>) }) } </ul> ) } ReactDOM.render(<ItemGrid items={data} />, document.getElementById("app")); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="app"></div> 

On the other hand, if you're retrieving the data from an asynchronous request it may not be available when the component is mounted and you'll need to handle the case when props.items is undefined/empty/null. 另一方面,如果要从异步请求中检索数据,那么在装入组件时它可能不可用,并且需要处理props.items为undefined / empty / null的情况。 In the example below we wrap the <ItemsGrid/> component in a <Parent/> component which passes the items as a prop to <ItemsGrid/> . 在下面的示例中,我们将<ItemsGrid/>组件包装在<Parent/>组件中,该组件将这些items作为道具传递给<ItemsGrid/> Initially the items is null , and after 3 seconds it changes to an array. 最初,这些itemsnull ,并在3秒钟后变为数组。 This simulates an asynchronous data source. 这模拟了一个异步数据源。

While items is null we return a list showing Loading... , and when items changes to a valid value we display the items. itemsnull我们返回一个显示Loading...的列表,当items更改为有效值时,我们将显示这些item。

 class Parent extends React.Component { constructor(props) { super(props); this.state = { data: null }; window.setTimeout(function(){ this.setState({ data: [{ ItemKey: 82521, ISBN: "158344422X", Title: "Butterflies And Moths", Publisher: "Benchmark Education", Illustrator: " " }, { ItemKey: 85938, ISBN: "9780452274426", Title: "In the Time of the Butterflies", Publisher: "Penguin Plume", Illustrator: " " }] }) }.bind(this), 3000); } render() { return ( <ItemGrid items={this.state.data} /> ) } } function ItemGrid(props) { var items = props.items; if (!items) { return ( <ul> <li>Loading...</li> </ul> ); } return ( <ul className='items-list'> { items && items.map(function(item, index) { return (<li key={item.ItemKey} className="items-list-item">{item.Title}</li>) }) } </ul> ) } ReactDOM.render(<Parent />, document.getElementById("app")); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="app"></div> 

If you are using redux, this is a very easy fix, but if you aren't: 如果您使用的是redux,这是一个非常简单的修复程序,但是如果您不这样做:

What is happening is when the component mounts, it immediately searches for props.items , but it is null . 发生的情况是,在安装组件时,它会立即搜索props.items ,但它为null You have an asynchronous event that eventually gets the data, but it's not doing it fast enough. 您有一个异步事件,该事件最终会获取数据,但是这样做的速度不够快。

The easiest way to fix this is to control what your .map is accepting by using a conditional statement before your component attempts to render content. 解决此问题的最简单方法是在组件尝试呈现内容之前,通过使用条件语句来控制.map接受的内容。

function ItemGrid (props){
    const items = props.items ? props.items : []
    return (
        <ul className='items-list'>
            {items.map(function(item, index){
                <li key={item.Title} className="items-list-item">
                </li>
            })}
        </ul>
    )
}

Check to see if props.items is null or not. 检查props.items是否为null If it is, render an empty array so it doesn't throw an error. 如果是,请渲染一个空数组,以免引发错误。 If it does exist, it'll use props.items . 如果确实存在,它将使用props.items

Please keep in mind that this will only work if a rerender attempt is made after you receive the array of data. 请记住,这仅在收到数据数组后尝试重新呈现时才有效。 I would personally uses promises and state to control rendering, because that will work in any situation. 我个人会使用promise和state来控制渲染,因为在任何情况下都可以使用。 It's a much more involved solution, but it's something you should know like the back of your hand as a React developer. 这是一个涉及更多的解决方案,但是作为React开发人员,这应该是您应该知道的。 Keep us updated. 保持更新。

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

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