Preface
In daily development, asynchronously obtaining data from the server side and rendering is a very high-frequency operation. When using React Class components in the past, we are already familiar with this operation, that is, in the componentDidMount of the Class component, ajax is used to obtain data and setState, and trigger component updates.
With the arrival of Hook, we can use the Hook writing method to replace the Class writing method in some scenarios. However, there are no functions such as setState and componentDidMount in the Hook. How can we obtain data asynchronously from the server and render it? This article will introduce how to use React's new feature Hook to write components and get data rendering.
Data rendering
Let's first look at a simple demo of data rendering
import React, { useState } from 'react'; function App() { const [data, setData] = useState({ products: [{ productId: '123', productName: 'macbook' }] }); return ( <ul> {(i => ( <li key={}> {} </li> ))} </ul> ); } export default App;
In the demo, an internal state called data is created through useState, which has a product list data to save product data. The App component renders product list data into the page through products in data.
But now it is a dead data. If we expect to get data from the server and render it, we need to fetch the server data when the component rendering is completed, and then change the state and trigger the rendering through setData. Next, we are going to use axios to get the data.
import React, { useState, useEffect } from 'react'; import axios from 'axios'; function App() { const [data, setData] = useState({ products: [{ productId: '123', productName: 'macbook' }] }); useEffect(async () => { const result = await axios( '/api/products?date=today', ); setData(); }); return ( <ul> {(i => ( <li key={}> {} </li> ))} </ul> ); } export default App;
The useEffect used in the code is one of hooks, called effect hooks. useEffect will fire every time the component is rendered, and we use it to get the data and update the state. But the above code is flawed, have you found it?
That's right, as long as you run it, you will find that the program has entered a dead loop. Because useEffect is not only triggered when the component didMounts, but also triggered when didUpdate. After obtaining data in useEffect, change state through setDate, trigger component rendering and update, and enter useEffect again and loop infinitely. This is not the result we want. What we wanted at first was just to get the data once when didMounts. So, in this case, we must pass an empty [] to the second parameter of the useEffect method, so that the logic in useEffect is executed only when the component didMounts is used.
import React, { useState, useEffect } from 'react'; import axios from 'axios'; function App() { const [data, setData] = useState({ products: [{ productId: '123', productName: 'macbook' }] }); useEffect(async () => { const result = await axios( '/api/products?date=today', ); setData(); },[]); //Focus return ( <ul> {(i => ( <li key={}> {} </li> ))} </ul> ); } export default App;
Although this mistake seems to be relatively low-level, it does make problems that many people often make when they are new to hooks.
Of course, the second parameter of useEffect can also be passed in a value. When there are values, useEffect will be triggered when these values are updated. If it is just an empty array, it will only be triggered when didMounts.
Also, execute this code and you will see the console warning, Promises and useEffect(async() => ...) are not supported, but you can call an async function inside an effect. So if you want to use async, you need to modify the writing method.
import React, { useState, useEffect } from 'react'; import axios from 'axios'; function App() { const [data, setData] = useState({ products: [{ productId: '123', productName: 'macbook' }] }); useEffect(() => { const fetchData = async()=>{ const result = await axios( '/api/products?date=today', ); setData(); } fetchData(); },[]); return ( <ul> {(i => ( <li key={}> {} </li> ))} </ul> ); } export default App;
Experience optimization
General applications will add loading to the interaction design of certain request processes to alleviate user anxiety. So how to implement it in the writing of Hook? This will be introduced below.
import React, { useState, useEffect } from 'react'; import axios from 'axios'; function App() { const [data, setData] = useState({ products: [{ productId: '123', productName: 'macbook' }] }); const [isLoading, setIsLoading] = useState(false); useEffect(() => { const fetchData = async()=>{ setIsLoading(true); const result = await axios( '/api/products?date=today', ); setData(); setIsLoading(false); } fetchData(); },[]); return ( {isLoading ? ( <div>Loading ...</div> ) : ( <ul> {(i => ( <li key={}> {} </li> ))} </ul> )}; } export default App;
This is achieved by adding a state called isLoading. We change the value of isLoading at the beginning and end of fetch to control the component content returned by return, so as to display the Loading component before the request and display the product list after the request.
Error handling
The request process often fails for various reasons, such as network, server errors, etc. Therefore, error handling is essential.
import React, { useState, useEffect } from 'react'; import axios from 'axios'; function App() { const [data, setData] = useState({ products: [{ productId: '123', productName: 'macbook' }] }); const [isLoading, setIsLoading] = useState(false); const [isError, setIsError] = useState(false); useEffect(() => { const fetchData = async()=>{ setIsError(false); setIsLoading(true); try{ const result = await axios( '/api/products?date=today', ); setData(); }catch(e){ setIsError(true); } setIsLoading(false); } fetchData(); },[]); return ( <div> {isError && <div>Something went wrong...</div>} {isLoading ? ( <div>Loading ...</div> ) : ( <ul> {(i => ( <li key={}> {} </li> ))} </ul> )}; </div> } export default App;
When a request error occurs, isError will be set to true. When the rendering is triggered, the error prompts the component will be rendered. The processing here is relatively simple. In real scenarios, you can add more complex logic when handling errors. isError will be reset every time the hook is run.
at last
After reading this, you have basically learned how to use React Hooks to get data and render components.
This is the article about how to use React Hooks to request data and render data. For more related React Hooks to request data and render content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!