詳解如何使用React Hooks請求數(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ù)并渲染呢?本文將會介紹如何使用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會在每次組件渲染的時(shí)候觸發(fā),我們使用它來獲取數(shù)據(jù)并更新state。但是上面的代碼是有缺陷的,你發(fā)現(xiàn)了嗎?
沒錯(cuò),只要你運(yùn)行一下,你就會發(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ò)誤比較低級,但確實(shí)比較多人在新上手hook時(shí)常常犯的問題。
當(dāng)然,useEffect第二個(gè)參數(shù),也可以傳入值。當(dāng)如果有值的時(shí)候,那useEffect會在這些值更新的時(shí)候觸發(fā)。如果只是個(gè)空數(shù)組,則只會在didMounts的時(shí)候觸發(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àn)優(yōu)化
一般的應(yīng)用在某些請求過程的交互設(shè)計(jì)上,會加上loading來緩解用戶焦慮。那在Hook的寫法中,如何實(shí)現(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;
這里通過加入一個(gè)叫isLoading的state來實(shí)現(xiàn)。我們在fetch的開始和結(jié)束去改變isLoading的值,來控制return返回的組件內(nèi)容,從而在請求前顯示Loading組件,在請求后顯示產(chǎn)品列表。
錯(cuò)誤處理
請求的過程經(jīng)常會由于各種原因失敗,比如網(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)請求出錯(cuò)時(shí),isError會被設(shè)置為true,觸發(fā)渲染時(shí),錯(cuò)誤提示組件就會被渲染出來。這里的處理比較簡單,在真實(shí)場景中,你可以在錯(cuò)誤處理時(shí)加入更復(fù)雜的邏輯。isError會在每次hook運(yùn)行的時(shí)候被重置。
最后
讀到這你已經(jīng)基本學(xué)會了如何使用React Hooks獲取數(shù)據(jù)并渲染組件了。
到此這篇關(guān)于如何使用React Hooks請求數(shù)據(jù)并渲染的文章就介紹到這了,更多相關(guān)React Hooks請求數(shù)據(jù)并渲染內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React實(shí)現(xiàn)控制減少useContext導(dǎo)致非必要的渲染詳解
這篇文章主要介紹了React如何有效減少使用useContext導(dǎo)致的不必要渲染,使用useContext在改變一個(gè)數(shù)據(jù)時(shí),是通過自己逐級查找對比改變的數(shù)據(jù)然后渲染,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-11-11React組件實(shí)例三大屬性state props refs使用詳解
這篇文章主要為大家介紹了React組件實(shí)例三大屬性state props refs使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09在React項(xiàng)目中實(shí)現(xiàn)一個(gè)簡單的錨點(diǎn)目錄定位
錨點(diǎn)目錄定位功能在長頁面和文檔類網(wǎng)站中非常常見,它可以讓用戶快速定位到頁面中的某個(gè)章節(jié),本文講給大家介紹一下React項(xiàng)目中如何實(shí)現(xiàn)一個(gè)簡單的錨點(diǎn)目錄定位,文中有詳細(xì)的實(shí)現(xiàn)代碼,需要的朋友可以參考下2023-09-09解決React報(bào)錯(cuò)Property value does not exist&n
這篇文章主要為大家介紹了React報(bào)錯(cuò)Property value does not exist on type HTMLElement解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12使用react context 實(shí)現(xiàn)vue插槽slot功能
這篇文章主要介紹了使用react context 實(shí)現(xiàn)vue插槽slot功能,文中給大家介紹了vue的slot的實(shí)現(xiàn)方法,需要的朋友可以參考下2019-07-07