This article mainly contains the following content:
- use
axios
Conduct simple data acquisition- Add state variables to optimize interactive experience
- Customize
hook
Perform data acquisition- use
useReducer
Renovation request
The main focus is 134 points! This article is mainly suitable forBeginners who are new to ReactAnd don't know how to regulate itReact
the person who gets the data.
Precondition: First prepare a backend interface, and the code is as follows:
@GetMapping("") public Map<String,Object> getListData(Integer size) { if ((size)){ size = 10; } List<Student> resultList = new ArrayList<>(); for (int i = 1; i <= size; i++) { Student student = new Student(); (i); ((int) (() * 100)); (().toString().split("-")[0]); (student); } Map<String, Object> hashMap = new HashMap<>(); ("data",resultList); ("status",200); return hashMap; }
Front-end adoptionreact 18.2 + axios
Construct the environment! After successfully setting up the environment, delete itThe code after deletion is as follows:
import { useState } from 'react' import './' import axios from 'axios' function App() { return ( <> <div> </div> </> ) } export default App
Simple data acquisition using axios
Modify firstThe code is as follows:
function App() { const [data, setData] = useState({ data: [] }) return ( <> <div> student name <ul> { (student =>{ return ( <li key={}> {} </li> ) }) } </ul> </div> </> ) }
First of all, useuseEffect
To obtain data, you need to pay attention to this step:
useEffect()
The arrow function inasync
Modification.useEffect()
The second parameter problem
First of all, inAdd the following code to
useEffect(async () => { const result = await axios("http://127.0.0.1:8080/student/") setData() })
At this time, the project cannot run normally, and the following error message will appear:
: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 (someId); // ... } fetchData(); }, [someId]); // Or [] if effect doesn't need props or state
Therefore, according to the error message, we need to modify our writing method as follows:
useEffect(() => { const fetchData = async () => { const result = await axios("http://127.0.0.1:8080/student/") setData() } fetchData(); })
After this modification, the project can run normally! The page can display data normally! But you must have found the following problems:stuName
Always changing. This is because in useuseEffect
When performing data acquisition, if no second parameter is specified, that is, its dependency,useEffect
Every time the render runs, it leads touseEffect
infinite loop.
So at this time we can add the second parameter, the code is as follows.
useEffect(() => { const fetchData = async () => { const result = await axios("http://127.0.0.1:8080/student/") setData() } fetchData(); },[])
Passing an empty array representation, without any dependencies, i.e.mounted
This method will not be triggered later.
If we need to rely on a certain parameter, that is, after a certain parameter changes, we need to reload the data, and then combine the parameters in the backend interfacesize
,existAdd the following code to:
const [size,setSize] = useState(5) useEffect(() => { const fetchData = async () => { const result = await axios(`http://127.0.0.1:8080/student/?size=${size}`) setData() } fetchData(); }, [size]) <div> student name <input type='number' value={size} onChange={event => setSize()} /> <ul> Omit other codes </ul> </div>
At this time, when we enter numbers in the input box, we will find the content changes. However, there are other problems with this. Whenever we enter a number, the effect of one-digit number is not obvious. When entering a 3-digit or 4-digit number, every time we enter a character, it will issue an http request. To obtain data, obviously this is not the effect we want. Therefore, it can be triggered manually instead, the code is as follows:
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/?size=${size}`) setData() } fetchData(); }, [query]) return ( <> <div> student name <input type='number' value={size} onChange={event => setSize()} /> <button onClick={() => setQuery(size)} >click me</button> <ul> { (student => { return ( <li key={}> {} </li> ) }) } </ul> </div> </> ) }
This can be triggered by manually clicking the query! But there are still some ways to optimize this method.query
andsize
Both state variables are used to trigger the query function, andquery
that issize
A copy of the , which can therefore be simplified to the following:
function App() { const [size, setSize] = useState(5) const [url,setUrl] = useState('http://127.0.0.1:8080/student/?size=5') const [data, setData] = useState({ data: [] }) useEffect(() => { const fetchData = async () => { const result = await axios(url) setData() } fetchData(); }, [url]) return ( <> <div> student name <input type='number' value={size} onChange={event => setSize()} /> <button onClick={() => setUrl(`http://127.0.0.1:8080/student/?size=${size}`)} >click me</button> <ul> { (student => { return ( <li key={}> {} </li> ) }) } </ul> </div> </> ) }
At this point, the simple data request is over! If it's just for the purpose of getting data, then that's the end!
Add state variables to optimize data loading process
Anyone who has written vue should knowelement-plus
In-housetable
All components have oneloading
Configuration item, used to display the current data acquisition status when making a data request. This is the effect achieved in this part!
const [isLoading, setIsLoading] = useState(false) //Omit other codes that have not been changeduseEffect(() => { const fetchData = async () => { setIsLoading(true) const result = await axios(url) setData() setIsLoading(false) } fetchData(); }, [url]) { isLoading ? (<div>Data is loading...</div>) : ( <ul> { (student => { return ( <li key={}> {} </li> ) }) } </ul> ) }
Then in ourJava
Add a delay code to the code:
try { (5); } catch (InterruptedException e) { (); }
After restarting the project, every request page after this will display a data loading process!
In addition to displaying the loading process of data, we can also add exception handling: the code is as follows, omitting other unchanged codes!
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() } catch (error) { setErrorInfo({ isError:true, message: }) } setIsLoading(false) } fetchData(); }, [url]) { && (<div>Data loading error: {}</div>) }
Custom hook for data acquisition
In the above code, we have written all the code in the samejsx
In the file, this is not conducive to our code maintenance [Imagine there are many state variables, how big is this file! 】; Therefore, it is necessary to extract the logic of the data request and put it into the newly createdIn the file, the code looks like this:
// 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() } catch (error) { setErrorInfo({ isError: true, message: }) } setIsLoading(false) } fetchData(); }, [url]) return [{ data, isLoading, errorInfo }, setUrl]; }
at this timeThe code is as follows:
function App() { const [size,setSize] = useState(5) const [{data,isLoading,errorInfo}, doFetch] = loadStudentList('http://127.0.0.1:8080/student/?size=5',{ data:[] }) return ( <> <div> student name <input type='number' value={size} onChange={event => setSize()} /> <button onClick={() => doFetch(`http://127.0.0.1:8080/student/?size=${size}`)} >click me</button> { && (<div>Data loading error: {}</div>) } { isLoading ? (<div>Data is loading...</div>) : ( <ul> { (student => { return ( <li key={}> {} </li> ) }) } </ul> ) } </div> </> ) }
This makes it much easier to compare before and after. Even if there are many data interfaces behind it, the contents of this file will not be too much! It's basically over here! But we can still use ituseReducer
Further optimize our requests!
Optimization with useReducer
In the above codeerrorInfo,isLoading
They are related, but are maintained separately, so in order to aggregate them together, you can use reducers for optimization:
import { useEffect, useState, useReducer } from 'react' import axios from 'axios' const dataFetchReducer = (state, action) => { switch () { case 'FETCH_INIT': return { ...state, isLoading: true, errorInfo: { isError:false, message:'', } }; case 'FETCH_SUCCESS': return { ...state, isLoading: false, errorInfo: { isError:false, message:'', }, data: , }; case 'FETCH_FAILURE': return { ...state, isLoading: false, errorInfo: { isError:true, 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: }); } catch (error) { dispatch({ type: 'FETCH_FAILURE',payload:error }); } // setIsLoading(false) } fetchData(); }, [url]) return [state, setUrl] }
The above is a detailed explanation of the method of using Axios to request data in React. For more information about Axios requesting data in React, please pay attention to my other related articles!