详解如何使⽤ReactHooks请求数据并渲染
前⾔
在⽇常的开发中,从服务器端异步获取数据并渲染是相当⾼频的操作。在以往使⽤React Class组件的时候,这种操作我们已经很熟悉了,即在Class组件的componentDidMount中通过ajax来获取数据并setState,触发组件更新。
随着Hook的到来,我们可以在⼀些场景中使⽤Hook的写法来替代Class的写法。但是Hook中没有setState、componentDidMount等函数,⼜如何做到从服务器端异步获取数据并渲染呢?本⽂将会介绍如何使⽤React的新特性Hook来编写组件并获取数据渲染。
数据渲染
先来看⼀个数据渲染的简单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>
react面试题hooks)
;
}
export default App;
在demo中,通过useState创建了⼀个叫data的内部state,该state中有⼀个产品列表数据保存产品数据。App组件通过data中的products来渲染产品列表数据到页⾯中。
但现在是写死的⼀个数据,如果我们期望从服务器端获取数据并渲染,那么就需要在组件渲染完成时fetch服务端数据,然后通过setData去改变state触发渲染。我们接下来准备⽤axios来获取数据。
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(
'c/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会在每次组件渲染的时候触发,我们使⽤它来获取数据并更新state。但是上⾯的代码是有缺陷的,你发现了吗?
没错,只要你运⾏⼀下,你就会发现程序进⼊了⼀个死循环。因为useEffect不仅在组件didMounts的时候被触发了,还在didUpdate的时候被触发了。在useEffect中获取数据后,通过setDate改变state,触发
组件渲染更新,从⽽⼜进⼊到了useEffect中,⽆限循环下去。这并不是我们想要的结果。我们最初想要的,只是希望在didMounts的时候获取⼀次数据⽽已。所以,这种情况下,我们必须要给useEffect⽅法的第⼆个参数传⼊⼀个空[],以使得useEffect中的逻辑只在组件didMounts的时候被执⾏。
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(
'c/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第⼆个参数,也可以传⼊值。当如果有值的时候,那useEffect会在这些值更新的时候触发。如果只是个空数组,则只会在didMounts的时候触发。
另外,执⾏这段代码,你会看到控制台警告,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(
'c/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;
⼀般的应⽤在某些请求过程的交互设计上,会加上loading来缓解⽤户焦虑。那在Hook的写法中,如何实现呢?下⾯将会介绍。
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(
'c/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来实现。我们在fetch的开始和结束去改变isLoading的值,来控制return返回的组件内容,从⽽在请求前显⽰Loading组件,在请求后显⽰产品列表。
错误处理
请求的过程经常会由于各种原因失败,⽐如⽹络、服务器错误等等。所以错误处理必不可少的。
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(
'c/api/products?date=today',
);
setData(result.data);
}catch(e){
setIsError(true);
}
setIsLoading(false);
}
},[]);
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,触发渲染时,错误提⽰组件就会被渲染出来。这⾥的处理⽐较简单,在真实场景中,你可以在错误处理时加⼊更复杂的逻辑。isError会在每次hook运⾏的时候被重置。
最后
读到这你已经基本学会了如何使⽤React Hooks获取数据并渲染组件了。
到此这篇关于如何使⽤React Hooks请求数据并渲染的⽂章就介绍到这了,更多相关React Hooks请求数据并渲染内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论