詳解如何使用React Hooks請求數(shù)據(jù)并渲染
前言
在日常的開發(fā)中,從服務器端異步獲取數(shù)據(jù)并渲染是相當高頻的操作。在以往使用React Class組件的時候,這種操作我們已經(jīng)很熟悉了,即在Class組件的componentDidMount中通過ajax來獲取數(shù)據(jù)并setState,觸發(fā)組件更新。
隨著Hook的到來,我們可以在一些場景中使用Hook的寫法來替代Class的寫法。但是Hook中沒有setState、componentDidMount等函數(shù),又如何做到從服務器端異步獲取數(shù)據(jù)并渲染呢?本文將會介紹如何使用React的新特性Hook來編寫組件并獲取數(shù)據(jù)渲染。
數(shù)據(jù)渲染
先來看一個數(shù)據(jù)渲染的簡單demo
import React, { useState } from 'react';
function App() {
const [data, setData] = useState({ products: [{
productId: '123',
productName: 'macbook'
}] });
return (
<ul>
{data.products.map(i => (
<li key={i.productId}>
{i.productName}
</li>
))}
</ul>
);
}
export default App;
在demo中,通過useState創(chuàng)建了一個叫data的內(nèi)部state,該state中有一個產(chǎn)品列表數(shù)據(jù)保存產(chǎn)品數(shù)據(jù)。App組件通過data中的products來渲染產(chǎn)品列表數(shù)據(jù)到頁面中。
但現(xiàn)在是寫死的一個數(shù)據(jù),如果我們期望從服務器端獲取數(shù)據(jù)并渲染,那么就需要在組件渲染完成時fetch服務端數(shù)據(jù),然后通過setData去改變state觸發(fā)渲染。我們接下來準備用axios來獲取數(shù)據(jù)。
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(
'https://c.com/api/products?date=today',
);
setData(result.data);
});
return (
<ul>
{data.products.map(i => (
<li key={i.productId}>
{i.productName}
</li>
))}
</ul>
);
}
export default App;
代碼中使用到的useEffect就是hook的其中一種,叫effect hook。useEffect會在每次組件渲染的時候觸發(fā),我們使用它來獲取數(shù)據(jù)并更新state。但是上面的代碼是有缺陷的,你發(fā)現(xiàn)了嗎?
沒錯,只要你運行一下,你就會發(fā)現(xiàn)程序進入了一個死循環(huán)。因為useEffect不僅在組件didMounts的時候被觸發(fā)了,還在didUpdate的時候被觸發(fā)了。在useEffect中獲取數(shù)據(jù)后,通過setDate改變state,觸發(fā)組件渲染更新,從而又進入到了useEffect中,無限循環(huán)下去。這并不是我們想要的結果。我們最初想要的,只是希望在didMounts的時候獲取一次數(shù)據(jù)而已。所以,這種情況下,我們必須要給useEffect方法的第二個參數(shù)傳入一個空[],以使得useEffect中的邏輯只在組件didMounts的時候被執(zhí)行。
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(
'https://c.com/api/products?date=today',
);
setData(result.data);
},[]); //重點
return (
<ul>
{data.products.map(i => (
<li key={i.productId}>
{i.productName}
</li>
))}
</ul>
);
}
export default App;
雖然看起來這個錯誤比較低級,但確實比較多人在新上手hook時常常犯的問題。
當然,useEffect第二個參數(shù),也可以傳入值。當如果有值的時候,那useEffect會在這些值更新的時候觸發(fā)。如果只是個空數(shù)組,則只會在didMounts的時候觸發(fā)。
另外,執(zhí)行這段代碼,你會看到控制臺警告,Promises and useEffect(async () => ...) are not supported, but you can call an async function inside an effect.。所以如果要使用async,需要修改下寫法。
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(
'https://c.com/api/products?date=today',
);
setData(result.data);
}
fetchData();
},[]);
return (
<ul>
{data.products.map(i => (
<li key={i.productId}>
{i.productName}
</li>
))}
</ul>
);
}
export default App;
體驗優(yōu)化
一般的應用在某些請求過程的交互設計上,會加上loading來緩解用戶焦慮。那在Hook的寫法中,如何實現(xiàn)呢?下面將會介紹。
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(
'https://c.com/api/products?date=today',
);
setData(result.data);
setIsLoading(false);
}
fetchData();
},[]);
return (
{isLoading ? (
<div>Loading ...</div>
) : (
<ul>
{data.products.map(i => (
<li key={i.productId}>
{i.productName}
</li>
))}
</ul>
)};
}
export default App;
這里通過加入一個叫isLoading的state來實現(xiàn)。我們在fetch的開始和結束去改變isLoading的值,來控制return返回的組件內(nèi)容,從而在請求前顯示Loading組件,在請求后顯示產(chǎn)品列表。
錯誤處理
請求的過程經(jīng)常會由于各種原因失敗,比如網(wǎng)絡、服務器錯誤等等。所以錯誤處理必不可少的。
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(
'https://c.com/api/products?date=today',
);
setData(result.data);
}catch(e){
setIsError(true);
}
setIsLoading(false);
}
fetchData();
},[]);
return (
<div>
{isError && <div>出錯了...</div>}
{isLoading ? (
<div>Loading ...</div>
) : (
<ul>
{data.products.map(i => (
<li key={i.productId}>
{i.productName}
</li>
))}
</ul>
)};
</div>
}
export default App;
當請求出錯時,isError會被設置為true,觸發(fā)渲染時,錯誤提示組件就會被渲染出來。這里的處理比較簡單,在真實場景中,你可以在錯誤處理時加入更復雜的邏輯。isError會在每次hook運行的時候被重置。
最后
讀到這你已經(jīng)基本學會了如何使用React Hooks獲取數(shù)據(jù)并渲染組件了。
到此這篇關于如何使用React Hooks請求數(shù)據(jù)并渲染的文章就介紹到這了,更多相關React Hooks請求數(shù)據(jù)并渲染內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
react native實現(xiàn)往服務器上傳網(wǎng)絡圖片的實例
下面小編就為大家?guī)硪黄猺eact native實現(xiàn)往服務器上傳網(wǎng)絡圖片的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08
使用react在修改state中的數(shù)組和對象數(shù)據(jù)的時候(setState)
這篇文章主要介紹了使用react在修改state中的數(shù)組和對象數(shù)據(jù)的時候(setState),具有很好的參考價值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
react-native-tab-navigator組件的基本使用示例代碼
本篇文章主要介紹了react-native-tab-navigator組件的基本使用示例代碼,具有一定的參考價值,有興趣的可以了解一下2017-09-09

