简体   繁体   English

等待对象数组加载并对其进行map()。 反应

[英]Wait for object array to load and map() it. React

I am trying to loop through json_obj after it loads using async XMLHttpRequest() but as json_obj is null at the start map() crashes. 我尝试使用异步XMLHttpRequest()加载后遍历json_obj,但由于json_obj在开始map()崩溃时为null。

Here is my code: 这是我的代码:

 import React, { Component, PropTypes} from 'react'; import ReactDOM from 'react-dom'; class ImageViewer extends React.Component { constructor() { super(); this.state = { loading: true, json_obj : null, link: "https://api.github.com/users/github/repos" } } componentDidMount() { var xhr = new XMLHttpRequest(); xhr.open("GET", this.state.link, true); xhr.onload = function (e) { if (xhr.readyState === 4) { if (xhr.status === 200) { this.setState({ json_obj :JSON.parse(xhr.responseText).sort(function(a, b){var keyA = new Date(a.updated_at),keyB = new Date(b.updated_at);if(keyA > keyB) return -1;if(keyA < keyB) return 1;return 0;})}); } else { console.error(xhr.statusText); } } }.bind(this); xhr.onerror = function (e) { console.error(xhr.statusText); }; xhr.send(null); } render() { return ( <div> {this.state.json_obj.map((obj, index) => { return ( <div > <h1>{obj.name}</h1> <h1>{obj.updated_at}</h1> </div> ) })} </div> ) }} ReactDOM.render( <ImageViewer />, document.getElementById('root') ); 
 <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="root"></div> 

I tried to use conditional rendering but it throws errors as well: 我尝试使用条件渲染,但它也会引发错误:

 import React, { Component, PropTypes} from 'react'; import ReactDOM from 'react-dom'; class ImageViewer extends React.Component { constructor() { super(); this.state = { loading: true, json_obj : null, link: "https://api.github.com/users/github/repos", stuff : {name:"loading", updated_at:"loading"} } } componentDidMount() { var xhr = new XMLHttpRequest(); xhr.open("GET", this.state.link, true); xhr.onload = function (e) { if (xhr.readyState === 4) { if (xhr.status === 200) { this.setState({ json_obj :JSON.parse(xhr.responseText).sort(function(a, b){var keyA = new Date(a.updated_at),keyB = new Date(b.updated_at);if(keyA > keyB) return -1;if(keyA < keyB) return 1;return 0;})}); } else { console.error(xhr.statusText); } } }.bind(this); xhr.onerror = function (e) { console.error(xhr.statusText); }; xhr.send(null); } render() { return ( <div> {(this.state.json_obj ? this.state.json_obj : this.state.stuff).map((obj, index) => { return ( <div > <h1>{obj.name}</h1> <h1>{obj.updated_at}</h1> </div> ) })} </div> ) }} ReactDOM.render( <ImageViewer />, document.getElementById('root') ); 
 <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="root"></div> 

So check if it's null and return something else: 因此,检查它是否为null并返回其他内容:

if (!this.state.json_obj) {
  return <div>Loading...</div>;
}

return (
  <div>
    {this.state.json_obj.map((obj, index) => (
      <div key={obj.name}>
        <h1>{obj.name}</h1>
        <h1>{obj.updated_at}</h1>
      </div>
    ))}
  </div>
)

Your code was throwing because this.state.stuff is an object and you can't iterate over an object with .map . 您的代码被抛出,因为this.state.stuff是一个对象,您无法使用.map遍历对象。 If this.state.json_obj is also an object and not an array you would need to do Object.keys(this.state.json_obj).map(... . 如果this.state.json_obj也是对象而不是数组,则需要执行Object.keys(this.state.json_obj).map(...

The first code you provided throws an error because json_obj is null as you mentioned. 您提供的第一个代码会引发错误,因为您提到的json_objnull But the second one throws an error because you are trying to map over the object this.state.stuff which you can not do. 但是第二个抛出一个错误,因为您试图map无法执行的对象this.state.stuff So there are actually a couple of things you can do: 因此,实际上您可以做几件事:

wrap stuff inside an array: stuff包装在数组中:

return (
            <div>
                {(this.state.json_obj ? this.state.json_obj : [this.state.stuff]).map((obj, index) => {
                            return (
                                <div >
                                    <h1>{obj.name}</h1>
                                    <h1>{obj.updated_at}</h1>
                                </div>
                            )
                })}
            </div>

or you can wrap it when defining it: 或者您可以在定义它时将其包装:

constructor() {
    super();
    this.state = {
        loading: true,
        json_obj : null,
        link: "https://api.github.com/users/github/repos",
        stuff : [{name:"loading", updated_at:"loading"}]
    }
}

or you can simply check if json_obj is available and rendering something else (or nothing) instead. 或者您可以简单地检查json_obj是否可用,然后呈现其他内容(或什么都不显示)。

renders nothing if json_obj is not available 如果json_obj不可用, json_obj呈现任何json_obj

return (
            <div>
                {this.state.json_obj && this.state.json_obj.map((obj, index) => {
                            return (
                                <div >
                                    <h1>{obj.name}</h1>
                                    <h1>{obj.updated_at}</h1>
                                </div>
                            )
                })}
            </div>
    )

renders a loading message when json_obj is not available json_obj不可用时呈现加载消息

return (
  <div>
    {
    this.state.json_obj ?
      this.state.json_obj.map((obj, index) => {
       return (
         <div >
           <h1>{obj.name}</h1>
           <h1>{obj.updated_at}</h1>
         </div>
       )
     }) : <div>Loading...</div>
    }
   </div>
  )

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

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