【问题标题】:setState() With Object.keys() Through Fetch Requests In Parent ComponentsetState() 和 Object.keys() 通过父组件中的获取请求
【发布时间】:2020-04-22 05:04:57
【问题描述】:

我正在尝试使用从父组件中的获取请求接收到的数据来设置状态。我收到一组对象,每个对象都有以下键:“name”、“artist”、“url”、“cover”、“lrc”和“theme”。我正在使用 Object.keys() 映射对象数据,但我想知道如何以这种方式设置状态,以便将具有这六个键的多个对象存储在状态中,因此我的状态将如下所示:

this.state = { data: [{ {...}, {...}, {...}, etc... }] }

一个大问题是我的数据 - 来自父级中的提取请求 - 没有在这个 tempComp 组件中呈现。我将数据作为道具(this.props.playlist)传递。为什么父级中获取的数据没有在 tempComp 组件中呈现,以及如何设置多个对象的状态,正如我在下面尝试使用 Object.keys() 时所做的那样?非常感谢任何建议。

import React, { Component } from 'react'

class tempComp extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      audio: [{
        name: '',
        artist: '',
        url: '',
        cover: '',
        lrc: '',
        theme: ''
      }]

    }
  }

  async componentDidMount() {
    console.log('playlist in componentDidMount()', this.props.playlist) //<--- AudioPlayer data should be coming in here

    var json = this.props.playlist;
    var arr = [];
    Object.keys(json).forEach(function (key) {
      arr.push(json[key]);
    });
    arr.map(item => {
      this.setState({
        audio: [{
          name: item.name,
          artist: item.artist,
          url: item.url,
          cover: item.cover,
          lrc: item.lrc,
          theme: item.theme
        }]
      })
    })
    console.log(this.state.audio);
  }


  render() {
    return (
      <div>

      </div>
    )
  }
}


export default tempComp

这里是父组件,为了澄清:


export default class PostContent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      id: '',
      episodeData: [],
    }
  }

  async componentDidMount(){
    const { id } = this.props.match.params;
    const response = await fetch(`http://localhost:5000/episode/${id}/playlist`);
    const jsonData = await response.json();
    this.setState({
      episodeData: jsonData, //this is working!...
      id: id
    });
    console.log(this.state.episodeData) //...see?
  }

  render() {
    return (
      <Fragment>

      <TempComp playlist={this.state.episodeData} />

        <AudioPlayer playlist={this.state.episodeData} />
        <Link id='home-link' to='/' activeClassName='active'>Homepage</Link>
        {this.state.episodeData.map((item, i) => (
          <div key={i} className="word-content">
            <h2 className="show-title">{item.post_title}</h2>
            <div className="episode-post-content">{item.post_content}</div>
            </div>
            ))}
            <Table data={this.state.data} />
            <div className="bottom-link">
              <Link id='home-link' to='/' activeClassName='active'>Homepage</Link>
            </div>
      </Fragment>
    )
  }
}

【问题讨论】:

  • 你被骗了。您不能在地图中设置状态,因为它是一种异步方法。你可以做一些技巧,但首先检查一下:stackoverflow.com/questions/47735600/…
  • 你为什么还要使用地图功能,你不能只是:- this.setState({ audio: arr });使用这个有什么问题吗?

标签: javascript reactjs


【解决方案1】:

您在这里被 setState 的工作方式欺骗了。这是asynchronous method,这意味着它不会与您的地图同步运行。您可以使用 setTimeout 或 await,我可以看到这是可能的,因为您的 componentDidMountasync 为前缀。但是,如果我可以冒昧的话,我建议您进行一些小的更改,如下所示:


const json = {
    apple: { yum: false },
    peach: { yum: true }
};

const yummyness = Object.keys(json).map(key => {
    return { yum: json[key].yum }
});

// yumminess will render:  [{ yum: false }, { yum: true }]
this.setState({ yummyness });

我在这里做了几件事:

  1. 如果数据没有变化,请将其分配给 const,您可以了解更多关于 here

  2. Map 返回一个数组。这可以像现在这样非常方便,因此我没有推送到您的 arr 值,而是返回了一个对象以防止您执行第二张地图。

  3. 最后,正如我之前提到的,setState 是异步的,而且有点笨拙!所以为了避免这种情况,我只是让地图做这件事,然后我把它分配给 yummyness。

  4. Bonus Round:我用过水果,但我保留了你的大部分命名方式。 json 是你的 props.playlist 和 yumminess 是你的 arr

希望这有帮助!

【讨论】:

  • 而且 - 如果你仍然有兴趣看这个:-) ...你有什么想法为什么父组件中获取的数据没有作为道具传递给子(TempComp)组件?当我在 componentDidMount() 方法中控制台日志“this.props.playlist”时,它返回一个空数组...
  • 能否请您:console.log this.state.episodeData 在您的渲染中返回上方,并解析一个虚拟数组并查看它是否作为 Props 进入 tempComp?谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-01
  • 1970-01-01
  • 2019-03-05
  • 2019-10-25
  • 2023-04-03
  • 2016-05-14
  • 2018-09-20
相关资源
最近更新 更多