react async
When fetching data in a JavaScript application, async-await
allows us to use imperative synchronous programming for fetching data. This means that our code will imperatively describe how the program will function and will operate along a single thread of operations. React, on the other hand, is a library that build UIs declaratively. This is often considered to be an opposing method to imperative programming, in which the developer describes what they want the program to do, rather than how they want it to behave. The combination of React and async-await
therefore leads to a mixed pattern in which we have both imperative code (for data fetching) and declarative code (for UI composition).
在JavaScript应用程序中获取数据时, async-await
允许我们使用命令式同步编程来获取数据。 这意味着我们的代码将强制性地描述程序如何运行以及如何沿着单个操作线程运行。 另一方面,React是一个以声明方式构建UI的库。 通常将其视为命令式编程的一种相反方法,在该方法中,开发人员描述他们希望程序执行的操作,而不是他们希望程序如何执行。 因此,React和async-await
的组合导致了一种混合模式,在该模式中,我们同时具有命令性代码(用于数据提取)和声明性代码(用于UI组合)。
React-async provides a declarative API to perform any REST API calls using a single React component, allowing declarative programming to be used throughout the application. It takes care of handling errors, promise resolution, and retrying promises, and deals with local asynchronous state.
React-async提供了一个声明式API,以使用单个React组件执行任何REST API调用,从而允许在整个应用程序中使用声明式编程。 它负责处理错误,承诺解析和重试承诺,并处理本地异步状态。
In this article, we will explain how the React-Async library helps us fetch data and run through some demonstrations of Helper components and functions.
在本文中,我们将解释React-Async库如何帮助我们获取数据并通过一些Helper组件和功能的演示来运行。
Let’s break down our topic into two parts: Declarative data fetching and Asynchronous API Calls in React.
让我们将主题分为两部分: 声明式数据获取和React中的异步API调用 。
Declarative data fetching is an approach used in calling APIs in which you declare what you want it to do for you without you worrying about all the things related to the call. It’s the opposite of the imperative approach where you also need to detail the steps you want the program to take.
声明式数据获取是一种用于调用API的方法,通过该方法,您可以声明要为您执行的操作,而不必担心与调用有关的所有事情。 这与命令式方法相反,在命令式方法中,您还需要详细说明希望程序执行的步骤。
Since JavaScript is synchronous by default and is single threaded, when we want to render a component that shows some data coming from an asynchronous call in previous versions of React, classes needed to be used. We had to use the component lifecycle methods to ensure the call happened when the component was mounted, and then we used the local state to manage the loading state.
由于JavaScript 默认情况下是同步的并且是单线程的,因此当我们想要渲染一个组件,该组件显示一些来自React早期版本中异步调用的数据时,需要使用类。 我们必须使用组件生命周期方法来确保调用在安装组件时发生,然后我们使用本地状态来管理加载状态。
Asynchronous requests will wait for a request to respond while the rest of the code continues to execute. Then when the time is right, a callback will spring these asynchronous requests into action.
异步请求将等待请求响应,而其余代码将继续执行。 然后,当时间合适时,回调将使这些异步请求生效。
Let’s demonstrate this by making a call to an endpoint to grab a list of currency prices:
让我们通过调用一个端点以获取货币价格列表来演示这一点:
import React, { Component } from 'react';
import axios from 'axios';
class App extends Component {
state = {
data: [],
error: '',
};
componentDidMount() {
axios
.get('https://api.coinmarketcap.com/v1/ticker/?limit=1')
.then(res => this.setState({ data: res.data }))
.catch(error => this.setState({ error }));
}
render () {
return (
<div className="App">
<ul>
{this.state.data.map(el => (
<li>
{el.name}: {el.price_usd}
</li>
))}
</ul>
</div>
);
}
}
export default App;
Note: Install axios by typing ‘npm install axios` into your terminal.
注意:在终端中输入“ npm install axios”来安装axios。
You can see this code live using this CodeSandbox page.
您可以使用此CodeSandbox页面实时查看此代码。
Here we make our API call in the componentDidMount function to ensure it runs as soon as the component is loaded. We can make sense of our data only after we go through the following steps:
在这里,我们在componentDidMount函数中进行API调用,以确保它在组件加载后立即运行。 只有经过以下步骤,我们才能理解我们的数据:
In the event of an error during the data fetching process:
在数据获取过程中发生错误时:
Here we are explicitly describing how and what to do at every step in fetching the data. Though the syntax and functions work correctly, the code can be re-written to be more efficient and in fewer lines if written declaratively. Let’s rewrite it using React-Async.
在这里,我们明确描述了在获取数据的每个步骤中如何做和做什么。 尽管语法和功能可以正常工作,但是如果以声明方式编写,则可以重新编写代码,以提高效率,并减少行数。 让我们使用React-Async重写它。
First, you need to install the package by typing npm install react-async
in your terminal. Then write your component with the following code:
首先,您需要在终端中键入npm install react-async
来安装软件包。 然后使用以下代码编写组件:
import React, { Component } from 'react';
import Async from 'react-async';
const loadJson = () =>
fetch("https://api.coinmarketcap.com/v1/ticker/?limit=1")
.then(res => (res.ok ? res : Promise.reject(res)))
.then(res => res.json())
const App = () => (
<Async promiseFn={loadJson}>
{({ data, error, isLoading }) => {
if (isLoading) return "Loading..."
if (error) return ``Something went wrong: ${error.message}``
if (data)
return (
<div>
{data.map(el => (
<li>
{el.name}: {el.price_usd}
</li>
))}
</div>
)
return null
}}
</Async>
)
export default App;
If you are using CodeSandbox, add React-Async from the dependency menu. If you’d like to see this code live, take a look at the React-Async example in CodeSandbox.
如果您使用的是CodeSandbox,请从依赖项菜单中添加React-Async。 如果您想实时观看此代码,请查看CodeSandbox中的React-Async示例 。
Here we have rewritten our component using hooks instead of classes. We first create a function loadJson
to handle our data fetching. Then, inside our App component, we utilize the Async
component made available through the React-Async library.
在这里,我们使用钩子而不是类重写了组件。 我们首先创建一个loadJson
函数来处理数据获取。 然后,在我们的App组件内部,我们利用可通过React-Async库使用的Async
组件。
Once our promise is resolved, props are made available to us to handle different scenarios.
一旦我们的诺言得以兑现,我们就可以使用各种道具来处理不同的情况。
isLoading
is available so we can display a user-friendly message while the data is yet to be loaded.
isLoading
可用,因此我们可以在尚未加载数据时显示一条用户友好的消息。
error
is available in case of an error during the fetch.
如果在提取期间error
则可以使用error。
data
is the actual data returned after the fetching is complete.
data
是提取完成后返回的实际数据。
In this example, we no longer have to use classes or lifecycle methods to load our data, nor do we need to tell React-Async how to process the data or how to update our state.
在这个例子中,我们不再需要使用类或生命周期方法来加载数据,也不需要告诉React-Async如何处理数据或如何更新状态。
React-Async manages the loading state through the isLoading
fallback prop, which is rendered until data
is ready to be rendered, that is, when the dependent asynchronous call resolves and returns the data.
React-Async通过isLoading
fallback isLoading
管理加载状态,该isLoading
会一直呈现直到准备好呈现data
为止,也就是说,当相关的异步调用解析并返回数据时。
React-Async comes with several helper components that make your JSX more declarative and less cluttered. Each of the helper components will only render its children when appropriate. We can rewrite our App function to look like this:
React-Async带有几个帮助程序组件 ,这些组件使您的JSX更具声明性,并且更加混乱。 每个帮助程序组件仅在适当时才渲染其子级。 我们可以将App函数重写如下:
const App = () => (
<Async promiseFn={loadJson}>
<Async.Loading>Loading...</Async.Loading>
<Async.Resolved>
{data => (
<div>
{data.map(el => (
<li>
{el.name}: {el.price_usd}
</li>
))}
</div>
)}
</Async.Resolved>
<Async.Rejected>
{error => `Something went wrong: ${error.message}`}
</Async.Rejected>
</Async>
)
Check out this example on CodeSandbox.
在CodeSandbox上查看此示例。
In this example, we have used the Async.Loading
, Async.Resolved
, and Async.Rejected
functions to simplify our code and make it more readable. Helper components provided by React-Async can take a React element or a function as children. When you provide a function, you’ll receive render props you can use in your component.
在此示例中,我们使用了Async.Loading
, Async.Resolved
和Async.Rejected
函数来简化代码并使代码更具可读性。 React-Async提供的帮助器组件可以将React元素或函数作为子元素。 提供功能时,您会收到可在组件中使用的渲染道具。
Let’s build a small user profile app that uses some more helper functions. Update your component to the following code:
让我们构建一个使用更多辅助功能的小型用户配置文件应用程序。 将组件更新为以下代码:
import React, { Component } from 'react';
import Async from 'react-async';
const loadUser = ({ userId }) =>
fetch('`https://reqres.in/api/users/${userId}'`)
.then(res => (res.ok ? res : Promise.reject(res)))
.then(res => res.json())
const UserPlaceholder = () => (
<div>
<div>User Details Loading</div>
</div>
)
const UserDetails = ({ data }) => (
<div className="details">
<img className="avatar" src={data.data.avatar} alt="" />
<div>
{data.data.first_name} {data.data.last_name}
</div>
</div>
)
const App = () => (
<Async promiseFn={loadUser} userId={1}>
<Async.Pending>
<UserPlaceholder />
</Async.Pending>
<Async.Fulfilled>{data => <UserDetails data={data} />}</Async.Fulfilled>
<Async.Rejected>{error => <p>{error.message}</p>}</Async.Rejected>
</Async>
)
export default App;
This is the code in CodeSandbox.
Let’s go over the functions we declared:
让我们看一下我们声明的函数:
loadUser
: We define this function to handle data fetching. It takes in a prop (userId
) and queries the API based on the id.
loadUser
:我们定义此函数来处理数据提取。 它接受一个prop( userId
)并根据id查询API。
userPlaceholder
: This is the fallback component that will be displayed when the promise has not yet resolved, that is, when the data has not finished loading.
userPlaceholder
:这是回退组件,将在承诺尚未解决(即数据尚未完成加载)时显示。
userDetails
: This component handles the actual display of the user data. It takes the data in via props and is only rendered when the promise has been resolved.
userDetails
:该组件处理用户数据的实际显示。 它通过道具接收数据,并且仅在诺言已解决时才呈现。
Async.Pending
,Async.Fulfilled
, and Async.Rejected
: These are functions to simplify our code and make it more readable.
Async.Pending
, Async.Fulfilled
和Async.Rejected
:这些功能可以简化我们的代码并使其更具可读性。
In this tutorial, we explored how to use the React-Async library to help us fetch data declaratively. We also looked at some of the helper functions it offers. To learn more about React-Async, check out the React-Async docs on GitHub.
在本教程中,我们探索了如何使用React-Async库来帮助我们声明式获取数据。 我们还研究了它提供的一些帮助器功能。 要了解有关React-Async的更多信息,请查看GitHub上的React-Async文档 。
react async