欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Axios在React中請求數(shù)據(jù)的方法詳解

 更新時間:2023年09月24日 09:06:13   作者:Supersist  
這篇文章主要給大家介紹了初學React,如何規(guī)范的在react中請求數(shù)據(jù),主要介紹了使用axios進行簡單的數(shù)據(jù)獲取,加入狀態(tài)變量,優(yōu)化交互體驗,自定義hook進行數(shù)據(jù)獲取和使用useReducer改造請求,本文主要適合于剛接觸React的初學者以及不知道如何規(guī)范的在React中獲取數(shù)據(jù)的人

本文主要有以下內(nèi)容:

  • 使用axios進行簡單的數(shù)據(jù)獲取
  • 加入狀態(tài)變量,優(yōu)化交互體驗
  • 自定義hook進行數(shù)據(jù)獲取
  • 使用useReducer改造請求

重點主要在134點! 本文主要適合于剛接觸React的初學者以及不知道如何規(guī)范的在React中獲取數(shù)據(jù)的人。

前置條件:首先準備一個后端接口,其代碼如下:

@GetMapping("list.do")
public Map<String,Object> getListData(Integer size) {
 ? ?if (Objects.isNull(size)){
 ? ? ? ?size = 10;
 ?  }
 ? ?List<Student> resultList = new ArrayList<>();
 ? ?for (int i = 1; i <= size; i++) {
 ? ? ? ?Student student = new Student();
 ? ? ? ?student.setStuId(i);
 ? ? ? ?student.setAge((int) (Math.random() * 100));
 ? ? ? ?student.setStuName(UUID.randomUUID().toString().split("-")[0]);
 ? ? ? ?resultList.add(student);
 ?  }
 ? ?Map<String, Object> hashMap = new HashMap<>();
 ? ?hashMap.put("data",resultList);
 ? ?hashMap.put("status",200);
 ? ?return hashMap;
}

前端采用react 18.2 + axios進行環(huán)境搭建!在成功搭建環(huán)境后,刪除掉App.jsx中的無關(guān)代碼,刪除后的代碼如下:

import { useState } from 'react'
import './App.css'
import axios from 'axios'
?
function App() {
 ?return (
 ? ?<>
 ? ? ?<div>
 ? ? ?</div>
 ? ?</>
  )
}
?
export default App

使用axios進行簡單的數(shù)據(jù)獲取

首先修改App.jsx代碼如下:

function App() {
 ?const [data, setData] = useState({
 ? ?data: []
  })
 ?return (
 ? ?<>
 ? ? ?<div>
 ? ? ?  student name
 ? ? ? ?<ul>
 ? ? ? ?  {
 ? ? ? ? ? ?data.data.map(student =>{
 ? ? ? ? ? ? ?return (
 ? ? ? ? ? ? ? ?<li key={student.stuId}>
 ? ? ? ? ? ? ? ?  {student.stuName}
 ? ? ? ? ? ? ? ?</li>
 ? ? ? ? ? ?  )
 ? ? ? ? ?  })
 ? ? ? ?  }
 ? ? ? ?</ul>
 ? ? ?</div>
 ? ?</>
  )
}

首先是使用useEffect進行數(shù)據(jù)獲取,在這一步需要注意如下:

  • useEffect()中的箭頭函數(shù)不能被async修飾。
  • useEffect()的第二個參數(shù)的問題

首先是第一點,在app.jsx中添加如下代碼

useEffect(async () => {
 ? ?const result = await axios("http://127.0.0.1:8080/student/list.do")
 ? ?setData(result.data)
})

此時項目不能夠正常運行,項目會出現(xiàn)如下的報錯信息:

react-dom.development.js:86 Warning: useEffect must not return anything besides a function, which is used for clean-up.

It looks like you wrote useEffect(async () => ...) or returned a Promise. Instead, write the async function inside your effect and call it immediately:

useEffect(() => { async function fetchData() { // You can await here const response = await MyAPI.getData(someId); // ... } fetchData(); }, [someId]); // Or [] if effect doesn't need props or state

因此根據(jù)錯誤信息,需要修改我們的寫法如下:

useEffect(() => {
 ? ?const fetchData = async () => {
 ? ? ? ?const result = await axios("http://127.0.0.1:8080/student/list.do")
 ? ? ? ?setData(result.data)
 ?  }
 ? ?fetchData();
})

這樣修改之后,項目可以正常運行了!頁面可以正常顯示數(shù)據(jù)了!但是細心的你一定發(fā)現(xiàn)了如下問題:stuName一直在變化。這是因為在使用useEffect進行數(shù)據(jù)獲取時,如果沒有指定第二個參數(shù),即他的依賴,則useEffect在每一次render都會運行,因此就導(dǎo)致了useEffect的無限循環(huán)。

所以此時我們添加第二個參數(shù)即可,代碼如下。

useEffect(() => {
 ? ?const fetchData = async () => {
 ? ? ? ?const result = await axios("http://127.0.0.1:8080/student/list.do")
 ? ? ? ?setData(result.data)
 ?  }
 ? ?fetchData();
},[])

傳遞空數(shù)組表示,沒有任何依賴,即在mounted后將不會觸發(fā)該方法。

如果說當我們需要依賴某個參數(shù)時,即某個參數(shù)發(fā)生改變后,我們需要重新加載數(shù)據(jù),此時結(jié)合后端接口中的參數(shù)size,在App.jsx中添加如下代碼:

const [size,setSize] = useState(5)
?
useEffect(() => {
 ? ?const fetchData = async () => {
 ? ? ? ?const result = await axios(`http://127.0.0.1:8080/student/list.do?size=${size}`)
 ? ? ? ?setData(result.data)
 ?  }
 ? ?fetchData();
}, [size])
?
<div>
 ? ? ?student name
 ? ? ? ? ?<input
 ? ? ? ? ? ?type='number'
 ? ? ? ? ? ?value={size}
 ? ? ? ? ? ?onChange={event => setSize(event.target.value)}
 ? ? ? ? ? ?/>
    <ul>
 ? ? 省略其他代碼
 ? ?</ul>
?
</div>

此時當我們在輸入框輸入數(shù)字時,就會發(fā)現(xiàn)內(nèi)容的改變。但是這樣存在了其他問題,每當我們輸入一個數(shù)時,一位數(shù)效果不明顯,在輸入3位數(shù)或者4位數(shù)時,每輸入一個字符,他都會發(fā)出一個http請求。進行數(shù)據(jù)獲取,顯然這不是我們要的效果。因此就可以改為手動觸發(fā),代碼如下:

function App() {
?
 ?const [size, setSize] = useState(5)
 ?const [query, setQuery] = useState('')
 ?const [data, setData] = useState({
 ? ?data: []
  })
?
 ?useEffect(() => {
 ? ?const fetchData = async () => {
 ? ? ?const result = await axios(`http://127.0.0.1:8080/student/list.do?size=${size}`)
 ? ? ?setData(result.data)
 ?  }
 ? ?fetchData();
  }, [query])
?
 ?return (
 ? ?<>
 ? ? ?<div>
 ? ? ?  student name
 ? ? ? ?<input
 ? ? ? ? ?type='number'
 ? ? ? ? ?value={size}
 ? ? ? ? ?onChange={event => setSize(event.target.value)}
 ? ? ? ?/>
 ? ? ? ?<button onClick={() => setQuery(size)} >click me</button>
 ? ? ? ?<ul>
 ? ? ? ?  {
 ? ? ? ? ? ?data.data.map(student => {
 ? ? ? ? ? ? ?return (
 ? ? ? ? ? ? ? ?<li key={student.stuId}>
 ? ? ? ? ? ? ? ?  {student.stuName}
 ? ? ? ? ? ? ? ?</li>
 ? ? ? ? ? ?  )
 ? ? ? ? ?  })
 ? ? ? ?  }
 ? ? ? ?</ul>
 ? ? ?</div>
 ? ?</>
  )
}

這樣就可以通過手動點擊查詢的方式觸發(fā)!但這種方式還有可以優(yōu)化的地方,querysize這兩個狀態(tài)變量都用于觸發(fā)查詢功能,且query就是size的一個復(fù)制,因此可以簡化為如下:

?
function App() {
 ?const [size, setSize] = useState(5)
 ?const [url,setUrl] = useState('http://127.0.0.1:8080/student/list.do?size=5')
 ?const [data, setData] = useState({
 ? ?data: []
  })
 ?useEffect(() => {
 ? ?const fetchData = async () => {
 ? ? ?const result = await axios(url)
 ? ? ?setData(result.data)
 ?  }
 ? ?fetchData();
  }, [url])
 ?return (
 ? ?<>
 ? ? ?<div>
 ? ? ?  student name
 ? ? ? ?<input
 ? ? ? ? ?type='number'
 ? ? ? ? ?value={size}
 ? ? ? ? ?onChange={event => setSize(event.target.value)}
 ? ? ? ?/>
 ? ? ? ?<button onClick={() => setUrl(`http://127.0.0.1:8080/student/list.do?size=${size}`)} >click me</button>
 ? ? ? ?<ul>
 ? ? ? ?  {
 ? ? ? ? ? ?data.data.map(student => {
 ? ? ? ? ? ? ?return (
 ? ? ? ? ? ? ? ?<li key={student.stuId}>
 ? ? ? ? ? ? ? ?  {student.stuName}
 ? ? ? ? ? ? ? ?</li>
 ? ? ? ? ? ?  )
 ? ? ? ? ?  })
 ? ? ? ?  }
 ? ? ? ?</ul>
 ? ? ?</div>
 ? ?</>
  )
}

到這一步簡單的數(shù)據(jù)請求就結(jié)束了!如果只是為了獲取數(shù)據(jù),則到此就結(jié)束了!

加入狀態(tài)變量,優(yōu)化數(shù)據(jù)加載過程

寫過vue的都應(yīng)該了解過在element-plus中的table組件都有一個loading配置項,當進行數(shù)據(jù)請求時,用于顯示當前的數(shù)據(jù)獲取狀態(tài)。這一部分實現(xiàn)的效果就是如此!

const [isLoading, setIsLoading] = useState(false)
// 省略沒有改變的其他代碼
useEffect(() => {
 ? ?const fetchData = async () => {
 ? ? ? ?setIsLoading(true)
 ? ? ? ?const result = await axios(url)
 ? ? ? ?setData(result.data)
 ? ? ? ?setIsLoading(false)
 ?  }
 ? ?fetchData();
}, [url])
{
 ? ?isLoading ? (<div>數(shù)據(jù)加載中...</div>) : (
 ? ? ? ?<ul>
 ? ? ? ? ?  {
 ? ? ? ? ? ? ? ?data.data.map(student => {
 ? ? ? ? ? ? ? ? ? ?return (
 ? ? ? ? ? ? ? ? ? ? ? ?<li key={student.stuId}>
 ? ? ? ? ? ? ? ? ? ? ? ? ?  {student.stuName}
 ? ? ? ? ? ? ? ? ? ? ? ?</li>
 ? ? ? ? ? ? ? ? ?  )
 ? ? ? ? ? ? ?  })
 ? ? ? ? ?  }
 ? ? ? ?</ul>
 ?  )
}

然后在我們的Java代碼中添加一個延時代碼:

try {
 ? ?TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
 ? ?e.printStackTrace();
}

重新啟動項目之后,在這之后的每一次請求頁面就會顯示一個數(shù)據(jù)的加載過程!

除了顯示數(shù)據(jù)的加載過程,我們還可以添加異常處理:代碼如下,省略了其他沒有改變的代碼!

const [errorInfo,setErrorInfo] = useState({
 ? ?isError:false,
 ? ?message:''
})
useEffect(() => {
 ? ?const fetchData = async () => {
 ? ? ? ?setIsLoading(true)
?
 ? ? ? ?setErrorInfo({
 ? ? ? ? ? ?isError:false,
 ? ? ? ? ? ?message:"no error",
 ? ? ?  })
 ? ? ? ?try {
 ? ? ? ? ? ?const result = await axios(url)
 ? ? ? ? ? ?setData(result.data)
 ? ? ?  } catch (error) {
 ? ? ? ? ? ?setErrorInfo({
 ? ? ? ? ? ? ? ?isError:true,
 ? ? ? ? ? ? ? ?message:error.message
 ? ? ? ? ?  })
 ? ? ?  }
 ? ? ? ?setIsLoading(false)
 ?  }
 ? ?fetchData();
}, [url])
?
{ errorInfo.isError && (<div>數(shù)據(jù)加載出錯: {errorInfo.message}</div>) }

自定義hook進行數(shù)據(jù)獲取

在上面的代碼中,我們都是將所有的代碼寫在了同一個jsx文件里面,這樣不利于我們進行代碼維護【想象一下有很多很多的狀態(tài)變量,這個文件得多大!】;因此需要將數(shù)據(jù)請求的邏輯提取出來放入至新建的request.js文件中,代碼如下所示:

?// request.js
import { useEffect, useState } from 'react'
import axios from 'axios'
export const loadStudentList = (initUrl, initData) => {
?
 ? ?const [url, setUrl] = useState(initUrl)
 ? ?const [data, setData] = useState(initData)
 ? ?const [isLoading, setIsLoading] = useState(false)
 ? ?const [errorInfo, setErrorInfo] = useState({
 ? ? ? ?isError: false,
 ? ? ? ?message: ''
 ?  })
?
 ? ?useEffect(() => {
 ? ? ? ?const fetchData = async () => {
 ? ? ? ? ? ?setIsLoading(true)
 ? ? ? ? ? ?setErrorInfo({
 ? ? ? ? ? ? ? ?isError: false,
 ? ? ? ? ? ? ? ?message: "no error",
 ? ? ? ? ?  })
 ? ? ? ? ? ?try {
 ? ? ? ? ? ? ? ?const result = await axios(url)
 ? ? ? ? ? ? ? ?setData(result.data)
 ? ? ? ? ?  } catch (error) {
 ? ? ? ? ? ? ? ?setErrorInfo({
 ? ? ? ? ? ? ? ? ? ?isError: true,
 ? ? ? ? ? ? ? ? ? ?message: error.message
 ? ? ? ? ? ? ?  })
 ? ? ? ? ?  }
 ? ? ? ? ? ?setIsLoading(false)
 ? ? ?  }
 ? ? ? ?fetchData();
 ?  }, [url])
 ? ?return [{ data, isLoading, errorInfo }, setUrl];
} 
?

此時App.jsx的代碼如下所示:

function App() {
?
 ?const [size,setSize] = useState(5)
 ?const [{data,isLoading,errorInfo}, doFetch] = loadStudentList('http://127.0.0.1:8080/student/list.do?size=5',{
 ? ?data:[]
  }) 
 ?return (
 ? ?<>
 ? ? ?<div>
 ? ? ?  student name
 ? ? ? ?<input
 ? ? ? ? ?type='number'
 ? ? ? ? ?value={size}
 ? ? ? ? ?onChange={event => setSize(event.target.value)}
 ? ? ? ?/>
 ? ? ? ?<button onClick={() => doFetch(`http://127.0.0.1:8080/student/list.do?size=${size}`)} >click me</button>
?
 ? ? ?  { errorInfo.isError && (<div>數(shù)據(jù)加載出錯: {errorInfo.message}</div>) }
 ? ? ?  {
 ? ? ? ? ?isLoading ? (<div>數(shù)據(jù)加載中...</div>) : (
 ? ? ? ? ? ?<ul>
 ? ? ? ? ? ?  {
 ? ? ? ? ? ? ? ?data.data.map(student => {
 ? ? ? ? ? ? ? ? ?return (
 ? ? ? ? ? ? ? ? ? ?<li key={student.stuId}>
 ? ? ? ? ? ? ? ? ? ?  {student.stuName}
 ? ? ? ? ? ? ? ? ? ?</li>
 ? ? ? ? ? ? ? ?  )
 ? ? ? ? ? ? ?  })
 ? ? ? ? ? ?  }
 ? ? ? ? ? ?</ul>
 ? ? ? ?  )
 ? ? ?  }
 ? ? ?</div>
 ? ?</>
  )
}

這樣前后一對比,就簡化了很多很多。即使后面有再多的數(shù)據(jù)接口按照這種方式,這個文件的內(nèi)容也不會太多!到這里基本上就可以結(jié)束了!不過我們還可以使用useReducer 進一步優(yōu)化我們的請求!

使用useReducer優(yōu)化

在上面的代碼中errorInfo,isLoading他們是相關(guān)的,但是卻是分別維護的,因此為了讓其聚合在一起可采用reducer進行優(yōu)化:

?
import { useEffect, useState, useReducer } from 'react'
import axios from 'axios'
?
const dataFetchReducer = (state, action) => {
 ? ?switch (action.type) {
 ? ? ? ?case 'FETCH_INIT':
 ? ? ? ? ? ?return {
 ? ? ? ? ? ? ? ?...state,
 ? ? ? ? ? ? ? ?isLoading: true,
 ? ? ? ? ? ? ? ?errorInfo: {
 ? ? ? ? ? ? ? ? ? ?isError:false,
 ? ? ? ? ? ? ? ? ? ?message:'',
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  };
 ? ? ? ?case 'FETCH_SUCCESS':
 ? ? ? ? ? ?return {
 ? ? ? ? ? ? ? ?...state,
 ? ? ? ? ? ? ? ?isLoading: false,
 ? ? ? ? ? ? ? ?errorInfo: {
 ? ? ? ? ? ? ? ? ? ?isError:false,
 ? ? ? ? ? ? ? ? ? ?message:'',
 ? ? ? ? ? ? ?  },
 ? ? ? ? ? ? ? ?data: action.payload,
 ? ? ? ? ?  };
 ? ? ? ?case 'FETCH_FAILURE':
 ? ? ? ? ? ?return {
 ? ? ? ? ? ? ? ?...state,
 ? ? ? ? ? ? ? ?isLoading: false,
 ? ? ? ? ? ? ? ?errorInfo: {
 ? ? ? ? ? ? ? ? ? ?isError:true,
 ? ? ? ? ? ? ? ? ? ?message:action.payload.message,
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  };
 ? ? ? ?default:
 ? ? ? ? ? ?throw new Error();
 ?  }
}
?
export const loadStudentList = (initUrl, initData) => {
 ? ?const [url, setUrl] = useState(initUrl)
 ? ?const [state, dispatch] = useReducer(dataFetchReducer, {
 ? ? ? ?isLoading: false,
 ? ? ? ?errorInfo: {
 ? ? ? ? ? ?isError: false,
 ? ? ? ? ? ?message: ''
 ? ? ?  },
 ? ? ? ?data: initData,
 ?  });
 ? ?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_FAILURE',payload:error });
 ? ? ? ? ?  }
 ? ? ? ? ? ?// setIsLoading(false)
 ? ? ?  }
 ? ? ? ?fetchData();
 ?  }, [url])
?
 ? ?return [state, setUrl]
}
?

以上就是使用Axios在React中請求數(shù)據(jù)的方法詳解的詳細內(nèi)容,更多關(guān)于Axios在React中請求數(shù)據(jù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于React實現(xiàn)一個todo打勾效果

    基于React實現(xiàn)一個todo打勾效果

    這篇文章主要為大家詳細介紹了如何基于React實現(xiàn)一個todo打勾效果,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-03-03
  • React渲染機制超詳細講解

    React渲染機制超詳細講解

    React整個的渲染機制就是React會調(diào)用render()函數(shù)構(gòu)建一棵Dom樹,在state/props發(fā)生改變的時候,render()函數(shù)會被再次調(diào)用渲染出另外一棵樹,重新渲染所有的節(jié)點,構(gòu)造出新的虛擬Dom tree
    2022-11-11
  • 重新理解?React?useRef原理

    重新理解?React?useRef原理

    這篇文章主要為大家介紹了React?useRef原理的深入理解分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • react hooks使用Echarts圖表中遇到的情況及相關(guān)配置問題

    react hooks使用Echarts圖表中遇到的情況及相關(guān)配置問題

    這篇文章主要介紹了react hooks使用Echarts圖表中遇到的情況及相關(guān)配置問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 在create-react-app中使用css modules的示例代碼

    在create-react-app中使用css modules的示例代碼

    這篇文章主要介紹了在create-react-app中使用css modules的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • react實現(xiàn)todolist的增刪改查詳解

    react實現(xiàn)todolist的增刪改查詳解

    這篇文章主要為大家介紹了react實現(xiàn)todolist的增刪改查,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • React中this丟失的四種解決方法

    React中this丟失的四種解決方法

    這篇文章主要給大家介紹了關(guān)于React中this丟失的四種解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用React具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-03-03
  • 基于react?vant實現(xiàn)彈窗搜索功能

    基于react?vant實現(xiàn)彈窗搜索功能

    這篇文章主要為大家詳細介紹了如何基于react?vant實現(xiàn)彈窗搜索功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2025-01-01
  • antd中form表單的wrapperCol和labelCol問題詳解

    antd中form表單的wrapperCol和labelCol問題詳解

    最近學習中遇到了些問題,所以給大家總結(jié),下面這篇文章主要給大家介紹了關(guān)于antd中form表單的wrapperCol和labelCol問題的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-02-02
  • React深入淺出分析Hooks源碼

    React深入淺出分析Hooks源碼

    在react類組件(class)寫法中,有setState和生命周期對狀態(tài)進行管理,但是在函數(shù)組件中不存在這些,故引入hooks(版本:>=16.8),使開發(fā)者在非class的情況下使用更多react特性
    2022-11-11

最新評論