繁体   English   中英

使用来自 API 的对象数组作为 JSON 进行 d3 可视化的问题

[英]Issue using array of objects from API as JSON for d3 visualization

所以我构建了一个 API ,它返回一个这样的数组:

[{"id":1,"name":"Josh","parent":null},
{"id":2,"name":"Peter","parent":1},{"id":3,"name":"Mary","parent":2}]

我可以在我的 react 应用程序上使用它来显示表格,但现在我想将它用作 d3 图表的输入。 正因为如此,我构建了一个 function,它采用一组对象并将其转换为一个大的分层对象。

function convert(array){    
    var map = {};
    for(var i = 0; i < array.length; i++){
        var obj = array[i];
        obj.children= [];

        map[obj.id] = obj;

        var parent = obj.parent || '-';
        if(!map[parent]){
            map[parent] = {
                children: []
            };
        }
        map[parent].children.push(obj);
    }

    return map['-'].children;

问题是,当我使用 axios.get 传递从 API 获得的内容时,它会给出一个未定义的错误,就好像它无法解析数组内的对象一样。

另一方面,如果我手动插入相同的数组:

const rawData2 = [{"id":1,"name":"Javier","parent":null},
{"id":2,"name":"Nerea","parent":1}, 
{"id":3,"name":"Yolo","parent":2}]

它没有问题。

我不知道还能尝试什么。 我尝试了 stringfy,使用 map 解析 json,如下所示:

var result = this.state.persons.map(person => ({id: person.id, name: person.name, parent: 
person.parent}))

没有任何效果。

有什么帮助吗?

EDIT: I think the problem has something to do with the fact that JS is asynchronous so when I pass the API response to my convert function I also pass some empty arrays before I actually pass the actual arrays from the data.

如何锁定数据以避免这种情况? 对不起,我缺乏技术词汇,但我对这种语言很陌生。

Edit2:这就是我从 API 检索数据的方式:

componentWillMount() {
    this._refreshAliens()
  }

  _refreshAliens () {
    axios.get('http://localhost:8080/aliens').then((response) => {
      this.setState({
        aliens: response.data
      })
     });

然后我只是简单地做: convert(this.state.aliens) 给我错误: Can add property children to undefined.

如果我 console.log(this.state.aliens):

我得到一些 [], [] 然后 (3) [{…}, {…}, {…}] 以及正确的数据。

编辑:

render() {
    let aliens = this.state.aliens.map((alien) => {
      return (
        <tr key={alien.id}>
          <td>{alien.id}</td>
          <td>{alien.name}</td>
          <td>{alien.type}</td>
          <td>{alien.planet}</td>
          <td>{alien.parent}</td>
          <td>
            <Button color="success" size="sm" className="mr-2" onClick={this.editAlien.bind(this, alien.id, alien.name, alien.planet)}>Edit</Button>
            <Button color="danger" size="sm" onClick={this.deleteAlien.bind(this, alien.id)}>Delete</Button>
          </td>
        </tr>
      )
      })
    const { all = [] } = this.state.aliens
      if (Array.isArray(all) && all.length === 0) {
        return <p>Loading...</p>
      } 
    return (

      <div className="App container">

          ...........

编辑错误:

错误:对象作为 React 子对象无效(发现:object 键为 {id, name, type, planet, parent})。 如果您打算渲染一组子项,请改用数组。

_refreshAliens/<src/App.js:60

  57 | }
  58 | _refreshAliens () {
  59 |   axios.get('http://localhost:8080/aliens').then((response) => {
> 60 |     this.setState({
     | ^  61 |       aliens: response.data
  62 |     })
  63 | 

在 API 请求发生期间,aliens state 将是一个空数组。 您还需要在转换 function 中处理这种情况。 添加 null 检查以避免在这种情况下返回错误。

function convert(array = []){    
    var map = {};
    for(var i = 0; i < array.length; i++){
        var obj = array[i];
        obj.children= [];

        map[obj.id] = obj;

        var parent = obj.parent || '-';
        if(!map[parent]){
            map[parent] = {
                children: []
            };
        }
        map[parent].children.push(obj);
    }

    return map['-'] ? map['-'].children : null;
}

编辑:如果 API 的数据可用,还要添加加载程序以避免进一步的错误,就像在您的渲染 function 中一样:

render() {
  const { aliens = [] } = this.state
  if (Array.isArray(aliens) && aliens.length === 0) {
    return <p>Loading...</p>
  }

  return (
    // Do your stuff...
  )

}

编辑 2:确保正确地从 state 中解构外星人。 生成的代码应该是这样的:

render() {
  const {aliens = []}= this.state;

  if (!Array.isArray(aliens) || aliens.length === 0) {
    return <p>Loading...</p>
  } 

  return (

      <div className="App container">
         {
            aliens.map((alien) => {
              return (
                <tr key={alien.id}>
                  <td>{alien.id}</td>
                  <td>{alien.name}</td>
                  <td>{alien.type}</td>
                  <td>{alien.planet}</td>
                  <td>{alien.parent}</td>
                  <td>
                    <Button color="success" size="sm" className="mr-2" onClick={this.editAlien.bind(this, alien.id, alien.name, alien.planet)}>Edit</Button>
                    <Button color="danger" size="sm" onClick={this.deleteAlien.bind(this, alien.id)}>Delete</Button>
                  </td>
                </tr>
              )
            })
         }

         // Other stuff...
      </div>
    )

暂无
暂无

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

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