react多个网络请求_如何优雅的在react-hook中进行网络请求

本文将介绍如何在使用React Hook进行网络请求及注意事项。

前言

Hook是在React 16.8.0版本中新加入的特性,同时在React-Native的0.59.0版本及以上进行了支持,使用hook可以不用class的方式的方式使用state,及类似的生命周期特性。

本片文章通过简单的网络请求数据的demo,来一起进一步认识react-hook这一特性,增加理解,涉及到的hook有useState, useEffect, useReducer等。

使用useState创建js页面

首先创建一个hook的功能页面demoHooks.js, 功能比较简单使用flatlist展示一个文本列表页面

```

const demoHooks = () => {

// 初始值

const [data, setData] = useState({hits: []});

_renderItem = ({item}) => {

console.log('rowData', item);

return(

{item.title}

)

};

return (

data={data.hits}

renderItem={this._renderItem}

/>

);

};

export default demoHooks;

```

使用useEffect请求数据

```

import React, {useState, useEffect} from 'react';

import {

Text,

View,

FlatList,

} from 'react-native';

import axios from 'axios'

// import CardView from 'react-native-cardview-wayne'

const demoHooks = () => {

// 初始值

const [data, setData] = useState({hits: []});

// 副作用

useEffect(async () => {

const result = await axios('https://hn.algolia.com/api/v1/search?query=redux');

setData(result.data);

console.log('执行了')

});

_renderItem = ({item}) => {

console.log('rowData', item);

return(

{item.title}

)

};

return (

data={data.hits}

renderItem={this._renderItem}

/>

);

};

export default demoHooks;

```

我们使用effect hook函数获取数据,这里我们用到了一个[axios](https://github.com/axios/axios)网络请求框架。运行上述代码后,会发现其中的console会一直循环打印,我们知道useEffect函数会在render更新后也就是原来的(componentDidUpdate)进行调用。这里我们在函数中调用了setData设置接口返回数据,触发页面的更新机制,就造成了死循环。

其实我们只是需要再页面加载后执行一次即可,也就是在class写法中componentDidMount()进行数据请求。

useEffect提供了第二参数,用于解决此类问题。这里传入一个空数组[],来让effect hook只在component mount后执行,避免在component update后继续执行。

```

// 副作用

useEffect(async () => {

const result = await axios('https://hn.algolia.com/api/v1/search?query=redux');

setData(result.data);

console.log('执行了')

},[]);

```

第二个参数是effect hook的依赖项列表,依赖项中数据发生变化的时候,hook就会重新执行,如果依赖项为空,hook认为没有数据发生变更,在组件更新的时候就不会在此执行。

你会遇到的问题

```

An effect function must not return anything besides a function, which is used for clean-up.

```

报错提示不能直接在useEffect中使用async,切实报错中也给出了解决方式,就是把async放在useEffect里面,修改如下,重新运行这个警告就消失了。

```

useEffect(() => {

const fetchData = async () => {

const result =  await axios('https://hn.algolia.com/api/v1/search?query=redux');

setData(result.data);

}

fetchData();

console.log('执行了')

},[]);

```

效果页面如下

手动触发hook请求

现在我们实现手动触发hook网络请求,修改代码如下,加一个按钮,点击按钮后获取以“redux”为关键词的列表数据

```

import React, {useState, useEffect} from 'react';

import {

Text,

View,

FlatList,

} from 'react-native';

import axios from 'axios'

import { TouchableOpacity } from 'react-native-gesture-handler';

const demoHooks = () => {

// 初始值

const [data, setData] = useState({hits: []});

const [search, setSearch] = useState('')

// 副作用

useEffect(() => {

const fetchData = async () => {

const result =  await axios(`https://hn.algolia.com/api/v1/search?query=${search}`);

setData(result.data);

}

fetchData();

console.log('执行了')

},[]);

_renderItem = ({item}) => {

console.log('rowData', item);

return(

{item.title}

)

};

_search = () => {

setSearch('redux')

}

return (

Search

data={data.hits}

renderItem={this._renderItem}

/>

);

};

export default demoHooks;

```

运行上述代码会发现,点击按钮后没有发生任何变化,细心的读者想必已经想到了,在代码中,useEffect hook的第二个参数是空数组,所以没有触发effect运行,重新获取数据,我们添加一下依赖项"search"到数组中,重新运行代码后,点击按钮就可看到我们的数据已经正确更新了。

// 副作用

useEffect(() => {

const fetchData = async () => {

const result =  await axios(`https://hn.algolia.com/api/v1/search?query=${search}`);

setData(result.data);

}

fetchData();

console.log('执行了')

},[search]);

```

添加一个加载框

数据请求是一个过程,通常在页面请求网络数据的时候会有一个友好的提示加载框,我们添加一个loading的state来实现一下。

import React, {useState, useEffect} from 'react';

import {

Text,

View,

FlatList,

} from 'react-native';

import axios from 'axios'

import { TouchableOpacity } from 'react-native-gesture-handler';

const demoHooks = () => {

// 初始值

const [data, setData] = useState({hits: []});

const [search, setSearch] = useState('')

const [isLoading, setIsLoading] = useState(false)

// 副作用

useEffect(() => {

const fetchData = async () => {

setIsLoading(true);

const result =  await axios(`https://hn.algolia.com/api/v1/search?query=${search}`);

setData(result.data);

setIsLoading(false);

}

fetchData();

console.log('执行了', isLoading)

},[search]);

_renderItem = ({item}) => {

// console.log('rowData', item);

return(

{item.title}

)

};

_search = () => {

setSearch('redux')

}

return (

Search

{

isLoading ?

The Data is Loading ...

:

data={data.hits}

renderItem={this._renderItem}

/>

}

);

};

export default demoHooks;

网络请求错误的处理

错误处理是在网络请求中是非常必要的,添加一个error状态,使用try/catch来进行捕获处理。

```

const [isError, setIsError] = useState(false)

// 副作用

useEffect(() => {

const fetchData = async () => {

setIsError(false)

setIsLoading(true);

try{

const result =  await axios(`https://hn.algolia.com/api/v1/search?query=${search}`);

setData(result.data);

}catch(error){

setIsError(true);

}

setIsLoading(false);

}

fetchData();

console.log('执行了', isLoading)

},[search]);

```

CommonFetchApi

我们将上述代码提取出一个通用的网络请求hook也就是自定义一个hook,包含initialData,error,initialState等;自定义hook也是一个函数,在其内部可以调用其他hook函数,使用“use”开头。

```

import React, {useState, useEffect} from 'react';

import {

Text,

View,

FlatList,

} from 'react-native';

import axios from 'axios'

import { TouchableOpacity } from 'react-native-gesture-handler';

const useDataApi = (initUrl, initData) => {

const [data, setData] = useState(initData);

const [url, setUrl] = useState(initUrl);

const [isLoading, setIsLoading] = useState(false);

const [isError, setIsError] = useState(false);

// 副作用

useEffect(() => {

const fetchData = async () => {

setIsError(false)

setIsLoading(true);

try{

const result =  await axios(url);

setData(result.data);

}catch(error){

setIsError(true);

}

setIsLoading(false);

}

fetchData();

},[url]);

return [{data, isLoading, isError}, setUrl];

}

const demoHooks = () => {

const [search, setSearch] = useState('react')

// 初始值

const [{data, isLoading,isError}, fetchData ] = useDataApi(

'https://hn.algolia.com/api/v1/search?query=redux',

{hits: []});

_renderItem = ({item}) => {

return(

{item.title}

)

};

_search = () => {

fetchData(`https://hn.algolia.com/api/v1/search?query=${search}`)

}

return (

Search

{

isError &&

网络请求出错了...

}

{

isLoading ?

The Data is Loading ...

:

data={data.hits}

renderItem={this._renderItem}

/>

}

);

};

export default demoHooks;

```

使用useReducer进行网络请求

以上通过综合使用useState 和 useEffect的方式实现了网络请求的loading,error,initstate的处理,可以看到我们在其中使用了4个useState处理响应的状态,其实我们也可以通过useReducer这个hook函数,来做统一管理,这里就类似于在class模式下,我们通常使用的react-redux进行数据流管理一样。

useReducer在很多时候可以用来替换useState, 接受两个参数(state, dispatch)返回一个计算后的新state,已达到更新页面的效果。

```

import React, {useState, useEffect, useReducer} from 'react';

import {

Text,

View,

FlatList,

} from 'react-native';

import axios from 'axios'

import { TouchableOpacity } from 'react-native-gesture-handler';

const fetchDataReducer = (state, action) => {

switch(action.type){

case 'FETCH_INIT':

return{

...state,

isLoading: true,

isError: false

}

case 'FETCH_SUCCESS':

return {

...state,

isLoading: false,

isErroe: false,

data: action.payload,

}

case 'FETCH_ERROR':

return {

...state,

isLoading: false,

isErroe: false,

data: action.payload,

}

break;

default:

return state;

}

}

const useDataApi = (initUrl, initData) => {

const [url, setUrl] = useState(initUrl);

const [state, dispatch] = useReducer(fetchDataReducer,{

data: initData,

isLoading: false,

isErroe: false

})

// 副作用

useEffect(() => {

const fetchData = async () => {

dispatch({type: 'FETCH_INIT'})

try{

const result =  await axios(url);

dispatch({type: 'FETCH_SUCCESS', payload: result.data})

}catch(error){

dispatch({type: 'FETCH_ERROR'})

}

}

fetchData();

},[url]);

return [state, setUrl];

}

const demoHooks = () => {

const [search, setSearch] = useState('react')

// 初始值

const [{data, isLoading,isError}, fetchData ] = useDataApi(

'https://hn.algolia.com/api/v1/search?query=redux',

{hits: []});

_renderItem = ({item}) => {

return(

{item.title}

)

};

_search = () => {

fetchData(`https://hn.algolia.com/api/v1/search?query=${search}`)

}

return (

Search

{

isError &&

网络请求出错了...

}

{

isLoading ?

The Data is Loading ...

:

data={data.hits}

renderItem={this._renderItem}

/>

}

);

};

export default demoHooks

页面销毁时中断网络请求

每个effect函数中都会返回一个函数用于清除操作,类似于class模式中的componentWillUnmount()进行移除监听操作,这个动作很重要,防止发生内存泄露及其他意想不到的情况,这里我们简单提供一个boolean值来在组件销毁时清除网络请求操作。

```

// 副作用

useEffect(() => {

let doCancel = false;

const fetchData = async () => {

dispatch({type: 'FETCH_INIT'})

try{

const result =  await axios(url);

if(!doCancel){

dispatch({type: 'FETCH_SUCCESS', payload: result.data})

}

}catch(error){

if(!doCancel){

dispatch({type: 'FETCH_ERROR'})

}

}

}

fetchData();

return ()=>{

doCancel = true;

}

},[url]);

```

总结

本文通过一个网络请求的demo讲述了react hooks部分API的使用及注意事项,这几个api也是平时开发工作中常见的,因此通过阅读本文,你应该可以收获如下内容:useState的使用

useEffect的使用及注意事项

useReducer的使用

自定义Hook的实现

本文对应的代码已上传至Github, [RN-DEMO](https://github.com/wayne214/RnDemo)觉得文章不错的,给我点个赞哇,关注一下呗!

技术交流可关注公众号【君伟说】,加我好友一起探讨

交流群:wayne214(备注技术交流)邀你入群,抱团学习共进步

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/488201.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS之代理模式

1 <!DOCTYPE html>2 <html lang"en">3 <head>4 <meta charset"UTF-8">5 <title>Document</title>6 </head>7 <body>8 <script>9 //1,买家 10 function maijia (argument) …

猴子会照镜子吗?科学家的这一研究意义非凡!

来源&#xff1a;中国经济大讲堂本期提要在《中国经济大讲堂》演讲中&#xff0c;中国科学院院士、中科院脑科学与智能技术卓越创新中心学术主任蒲慕明指出&#xff0c;自闭症患者、严重脑疾病可能伴有自我意识损伤的现象。我们通过各种训练方法&#xff0c;可以使猴子学会识别…

博客开篇。

【README.MD】: this is a blog for 13203361793163.com. just about HTML 、Css 、 JavaScript and a little PHP. Practice is most important to learn and master all knowledge, only in this way , can we make our career better and better . 转载于:https://www.cnbl…

Science | 闵明玮等揭示细胞如何做出命运决定

来源&#xff1a;BioArt细胞命运决定我们体内的每个细胞都会面临着一个关乎命运的选择&#xff1a;要不要复制产生一个新的细胞。这个重大选择关系到人体发育和维持稳态等生理过程&#xff0c;因此它的失调也与癌症等疾病的发生发展有着密切联系。在人体中&#xff0c;大部分的…

itext html 转换 pdf文件,利用itext实现html转pdf文档

Link: http://keyknight.blog.163.com/blog/static/366378402009431104941637/利用itext实现html转pdf文档的代码实在是太简单了&#xff1a;Document pdf new Document(PageSize.A4, 50, 50, 50, 50);try {PdfWriter.getInstance(pdf, new FileOutputStream("d:/t.pdf&q…

图解机器学习:人人都能懂的算法原理

来源&#xff1a;机器学习研究组订阅号算法公式挺费神&#xff0c;机器学习太伤人。任何一个刚入门机器学习的人都会被复杂的公式和晦涩难懂的术语吓到。但其实&#xff0c;如果有通俗易懂的图解&#xff0c;理解机器学习的原理就会非常容易。本文整理了一篇博客文章的内容&…

python gil锁问题_Python的GIL与线程安全问题?[closed]

由于一些历史原因&#xff0c;CPython的GIL使得Python同一个时刻只能有一个线程在运行&#xff0c;这使得线程只能用于IO型任务&#xff0c;虽然异步更胜一筹。但是既然同一个时刻只能有一个线程运行那为什么还会有线程安全&#xff0c;线程非安全之类的概念。threading模块提供…

html5页面主题,HTML5页面开发笔记

页面由设计决定, 所以首先聊聊设计稿前戏, 页面设计规范PSD设计稿的图层 "分组" 以及图层 "命名":设计稿中的每一个元素, 比如 唱片机, 设计师需要将所有属于唱片机的图层全部打到一个图层组里, 并且命名这个图层组为唱片机.这样开发人员可以快速的去单独导…

AC日记——Mato的文件管理 bzoj 3289

3289 思路&#xff1a; 莫队求区间逆序对个数&#xff0c;树状数组维护&#xff1b; 代码&#xff1a; #include <bits/stdc.h> using namespace std; #define maxn 50005 int bel[maxn],blo; struct QueryType {int l,r,id;bool operator<(const QueryType pos)const…

Python 什么时候会被取代?

来源&#xff1a;CSDN译者 | 弯月&#xff0c;责编 | 郭芮以下是译文&#xff1a; Python经过了几十年的努力才得到了编程社区的赏识。自2010年以来&#xff0c;Python得到了蓬勃发展&#xff0c;并最终超越了C、C#、Java和JavaScript。但是&#xff0c;这种趋势将持续到什么时…

java负数右移_Java中的按位右移运算符 - Break易站

在C / C 中&#xff0c;只有一个右移运算符>>&#xff0c;它只能用于正整数或无符号整数。在C / C 中不推荐使用右移运算符来表示负数&#xff0c;当用于负数时&#xff0c;输出依赖于编译器。与C 不同&#xff0c;Java支持以下两个右移操作符。Java中的按位右移运算符1)…

Android开发艺术探究Note

第一章&#xff1a;Activity的生命周期和启动模式 生命周期onPause表示activity正在停止&#xff0c;onPaus必须先执行完&#xff08;栈顶的activity&#xff09;&#xff0c;新的activity的onResume才会执行。onStop表示activity即将停止&#xff08;透明不会执行&#xff09;…

html设置焦点图片,HTML设置焦点

**插件简介**这是一款很有特点的HTML5图片切换焦点图动画&#xff0c;点击左右按钮即可将图片进行弹性切换&#xff0c;图片在被切换时&#xff0c;都会左右晃动几下&#xff0c;产生一定的弹性缓冲动画效果。[contenteditable]:focus{outline: none;}如果input失去焦点时,有进…

烧脑:宇宙时空结构是量子纠错码

来源&#xff1a;Future远见现在越来越多的理论物理学家开始相信&#xff0c;时空起源于纠缠的量子信息。粗略地讲&#xff0c;时空中最重要的“相邻”概念&#xff0c;可以认为是起源于量子纠缠&#xff1a;有纠缠就是相邻&#xff0c;没有纠缠就是不相邻。如果你相信这一观念…

dataframe 取2列_DataFrame通过两列进行分组,并获取另一列的计数

新手程序员在这里寻求帮助。我有一个看起来像这样的数据框&#xff1a;Cashtag Date Message0 $AAPL 2018-01-01 "Blah blah $AAPL"1 $AAPL 2018-01-05 "Blah blah $AAPL"2 $AAPL 2019-01-08 "Blah blah $AAPL"3 $AAPL 2019-02-09 "Blah bl…

解决黑苹果的887驱动问题

使用audio_cloverALC工具&#xff0c;下载地址https://github.com/toleda/audio_CloverALC/blob/master/audio_cloverALC-120.command.zip。 首先需要挂载efi分区 1 promote:~ asher$ diskutil list2 /dev/disk0 (internal, physical):3 #: TYPE NAME…

tornado 获取html,python使用tornado实现简单爬虫

本文实例为大家分享了python使用tornado实现简单爬虫的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下代码在官方文档的示例代码中有,但是作为一个tornado新手来说阅读起来还是有点困难的,于是我在代码中添加了注释,方便理解,代码如下:# codingutf-8#!/usr/bin/env p…

李德毅院士:通用人工智能十问

来源&#xff1a;学术头条共识&#xff1a;智能是学习的能力&#xff0c;以及解释、解决问题的能力&#xff1b;人工智能是脱离生命体的智能&#xff0c;是人类智能的体外延伸&#xff1b;通用人工智能通过不断学习&#xff0c;积累本领&#xff0c;进化成长&#xff0c;能够面…

gdt描述_全局描述符表GDT

写在前面添油加醋系列第二弹——剖析GDT话说C语言的话除了刷刷OJ外&#xff0c;就是用来实现操作系统这个大头了。C语言比C少了很多很多臃肿的语法特性&#xff0c;写起来非常优美(至少写操作系统是这样的)。虽说C有许多的奇技淫巧&#xff0c;一个算法有N种实现方法&#xff0…

咸阳高考成绩查询2021,2021咸阳市地区高考成绩排名查询,咸阳市高考各高中成绩喜报榜单...

距离2018年高考还有不到一个月的时间了&#xff0c;很多人在准备最后冲刺的同时&#xff0c;也在关心高考成绩。2018各地区高考成绩排名查询,高考各高中成绩喜报榜单尚未公布&#xff0c;下面是往年各地区高考成绩排名查询,高考各高中成绩喜报榜单&#xff0c;想要了解同学可以…