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

