在 React 类中获取数据并更新状态
介绍
你是否需要在 React 组件中渲染来自服务器的数据?我猜是的,你曾经需要过。但如何实现这一点并不总是很清楚。你可能会问:
- 这是否必须在用户交互之后发生?
 - 我需要 Redux/Mobx 吗?
 - 是否有适合这种用例的特定 React 库?
 
我想解释如何使用从服务器获取的数据来更新类组件中的组件状态,并希望消除有关该主题的任何困惑。
假设我们有一个关于哈利波特的应用程序。您可以阅读有关角色、他们的背景故事、每本书的详细信息等。此应用程序中的一个组件列出了哈利波特系列中的每一本书。书籍详细信息需要来自 Rest API,因此让我们看看如何在 React 类组件中执行此操作。
渲染时的状态
我们要解决的问题是:
当组件加载时,我需要它向我的 REST API 创建一个请求来提取一些数据。
那么问题是,“我在组件中的哪里发出这个请求?”答案是在生命周期方法之一中。
类组件生命周期方法
尽管 React 组件中有几种生命周期方法,但我们将重点关注的获取请求方法是componentDidMount()和componentWillUnmount()。
      import React from 'react';
class ProductList extends React.Component {
    componentDidMount() {
        // make fetch request
    }
    
    componentWillUnmount() {
        // make fetch request
    }
    
    render() {
        return (
            <ul>
                <li />
            </ul>
        )
    }
}
    
组件将卸载()
当需要在组件卸载时执行操作时,可以使用 componentWillUnmount() 方法。常见场景包括取消订阅实时监听器或跟踪卸载事件。在本指南的其余示例中,我们不需要 componentWillUnmount ( )方法,因此我们将使用componentDidMount()方法。
组件挂载()
根据 React 文档:
componentDidMount() 在组件被挂载(插入到树中)后立即被调用。
componentDidMount 方法是向服务器请求数据的最佳位置,因为即使设置状态会导致第二次渲染,但它发生在浏览器更新屏幕之前。用户不会看到中间状态。
那么我该如何更新状态?
我们要做的是获取《哈利波特》书籍列表,并将它们显示在列表中。
我首先想在我们的初始状态设置一个书籍对象:
      class BookList extends React.Component {
    state = {
        books: []
    }
}
    
我们将把我们的书籍呈现为如下的无序列表:
- 哈利·波特与魔法石
 - 哈利·波特与密室
 - 哈利·波特与阿兹卡班的囚徒
 - ETC
 
      class BookList extends React.Component {
    state = {
        books: []
    }
    
    render() {
        return (
            <ul>
                {this.state.books.map((book) => (
                    <li key={book.id}>{book.name}</li>
                ))}
            </ul>
        )
    }
}
    
为了用书籍填充我们的状态,我们需要使用 componentDidMount() 生命周期方法。
      ..
componentDidMount() {
    fetch('https://some-api.com/harry-potter')
    .then((response) => response.json())
    .then(booksList => {
        this.setState({ books: booksList });
    });
}
..
    
刚才到底发生了什么?
这里发生的事情是:
- 该组件将开始插入到 DOM 中。
 - 初始渲染发生(书籍数组为空)。
 - 然后调用componentDidMount()
 - 一旦该请求成功完成,就会调用setState()并且books属性将使用所有哈利波特书籍进行更新。
 
调用setState()会触发新的渲染,并且每本书现在都会显示在无序列表中。
以下是完整的示例:
      class BookList extends React.Component {
    state = {
        books: []
    }
    
    componentDidMount() {
        fetch('https://some-api.com/harry-potter')
        .then((response) => response.json())
        .then(booksList => {
            this.setState({ books: booksList });
        });
    }
    
    render() {
        return (
            <ul>
                {this.state.books.map((book) => (
                    <li key={book.id}>{book.name}</li>
                ))}
            </ul>
        )
    }
}
    
根据用户事件更新状态
那么当我们想要在组件初始加载后发出异步请求时该怎么办?如果我想在用户单击按钮时获取书籍怎么办?我们可以将获取调用移出 componentDidMount() 方法,并在新方法中调用我们的 API,我们将该方法定义为fetchBooks():
      class BookList extends React.Component {
    state = {
        books: []
    }
    
    fetchBooks = () => {
        fetch('https://some-api.com/harry-potter')
        .then((response) => response.json())
        .then(booksList => {
            this.setState({ books: booksList });
        });
    }
    
    render() {
        return (
        <>
            <button onClick={this.fetchBooks}>Load Books</button>
            {this.books.length > 0 && (
                <ul>
                    {this.state.books.map((book) => (
                        <li key={book.id}>{book.name}</li>
                    ))}
                </ul>
            )}
            
        </>
        )
    }
}
    
我们在这里所做的就是添加一个按钮,当单击该按钮时,它会发出与之前在componentDidMount()方法中相同的获取请求。我还在图书列表的渲染周围添加了一个条件,即仅当图书数量超过零本时才渲染列表。
结论
在 React 应用程序中,从服务器获取和渲染数据非常常见。React.Component类为我们提供了一个生命周期方法,使此操作变得容易,我建议使用 componentDidMount ()来发出组件加载时发生的任何异步请求。
我们将在另一个指南中讨论如何在功能组件中执行相同的任务。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
                                
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                
                            
                                    
                                    
                                    
                                    
    
    
            
  
        
请先 登录后发表评论 ~