首页 > 解决方案 > 如何仅在对象内的所有 id 完成获取后才设置状态

问题描述

我正在尝试在获取操作循环完成后设置状态(在数据获取完成之前显示加载器)。我正在async通过 data.map 使用一个函数来执行此操作,但它仍在运行,并且我setState正在它之前发生。任何想法如何解决这个问题,我在这里错过了什么。

这是我的代码:

class App extends Component {
      constructor() {
        super();
        this.state = { 

          posts: [],
          loading: true
        }
      }

      async componentDidMount() {
        await this.fetchNews();    
        this.setState({loading: false})

      }

      async fetchNews() {        
        await fetch('https://hacker-news.firebaseio.com/v0/newstories.json')
          .then(response => response.json())
          .then((data) => {
            data.slice(0,10).map((newsId) => {
               fetch('https://hacker-news.firebaseio.com/v0/item/' + newsId + '.json')
                .then(response => response.json())
                .then((itemDetail) => {
                  this.setState({ posts: [...this.state.posts, itemDetail] })
                  console.log('Fetching in progress');                  
                })
                return true;
            })
            console.log('done finished');
          })           
        }    
      render() {    
        var post = this.state.posts;
        const loading = this.state.loading;
        console.log(post)
        const listItems = post.map((link) =>
        <li key={link.id}>{link.title}</li> );

      return <div>
                  {loading ? <Loader type="MutatingDots" color="#somecolor" height={80} width={80} /> : <div>{listItems}</div>}        
        </div>;
     }    
}

export default App;

这是我的控制台日志,当提取仍在运行时,您可以看到在开始时打印完成的消息。 在此处输入图像描述

标签: javascriptreactjs

解决方案


在 map 中执行异步操作,请使用Promise.all,它会正常工作

const fetchNews = async () =>
  await fetch('https://hacker-news.firebaseio.com/v0/newstories.json')
    .then((response: any) => response.json())
    .then(async (data: any) => {
      let news = data.slice(0, 10);
      await Promise.all(
        news.map(async (newsId: any) => {
          await fetch('https://hacker-news.firebaseio.com/v0/item/' + newsId + '.json')
            .then((response: any) => response.json())
            .then((itemDetail: any) => {
               this.setState({ posts: [...this.state.posts, itemDetail] });
              console.log('Fetching in progress', newsId);
            });
          return true;
        })
      );
      console.log('done finished');
    });

推荐阅读