最新使用React hooks,些许又多了不少摸鱼时间,2024年最新C C++高分面试指南

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

            </li>
    })}</ul>
}

}


**函数组件:**



// 函数组件
function List(props) {
const { list } = props

return <ul>{list.map((item, index) => {
    return <li key={item.id}>
        	<span>{item.title}</span>
        </li>
})}</ul>

}


#### (2)函数组件的特点


**函数组件的特点是:**


* 没有组件实例;
* 没有生命周期;
* 没有 `state` 和 `setState` ,只能接收 `props` 。


#### (3)class组件的问题


上面我们说到了函数组件是一个纯函数,只能接收 `props` ,没有任何其他功能。而 `class` 组件拥有以上功能,但是呢,`class` 组件会存在以下问题:


* 大型组件很难拆分和重构,很难测试(即 `class` 不易拆分);
* 相同业务逻辑,分散到各个方法中,逻辑混乱;
* 复用逻辑变得复杂,如 `Mixins` 、 `HOC` 、 `Render Props` 。


因此,有了以上问题的出现,也就有了 `React Hooks` 。


#### (4)React 组件


* `React` 组件更易于用**函数**来表达:
* `React` 提倡函数式编程,即 `view=fn(props)` ;
* 函数更**灵活**,更易**拆分**,更易**测试**;
* 但**函数组件**太简单,需要增强能力 ——因此,有了 `React Hooks` 。


## 二、🪕几种 Hooks


### 1、State Hook🗞️


#### (1)让函数组件实现state和setState


* 默认函数组件是没有 `state` 的;
* 函数组件是一个纯函数,执行完即销毁,无法存储 `store` ;
* 需要 `State Hook` ,即把 `store` 功能 “钩” 到纯函数中。


#### (2)举例阐述


假设我们现在要通过点击按钮,来修改设定的某个值。现在我们用 `hooks` 中的 `useState` 来处理。**具体代码如下:**



import React, { useState } from ‘react’

function ClickCounter() {
// 数组的解构
// useState 就是一个 Hook “钩”,最基本的一个 Hook
const [count, setCount] = useState(0) // 传入一个初始值,初始值可以是数值/字符串/数组/对象等类型

const [name, setName] = useState('星期一研究室')

// const arr = useState(0)
// const count = arr[0]
// const setCount = arr[1]

function clickHandler() {
    setCount(count + 1)
    setName(name + '2021')
}

return <div>
    <p>你点击了 {count} 次 {name}</p>
    <button onClick={clickHandler}>点击</button>
</div>

}

export default ClickCounter


此时浏览器的显示效果如下:


![useState](https://img-blog.csdnimg.cn/e740acee99d0458989d671fbb0ac4082.gif#pic_center)


在上面的代码中, `count` 是一个 `state` 的值, `setCount` 是修改 `state` 的一个函数。同理, `name` 也是一个 `state` 的值, `setName` 是修改 `name` 值得一个函数。


如果使用 `hooks` 来修改 `state` 值的话,那么我们只需要以 `const [count, setCount] = useState(0)` 这种形式去进行,便可修改最后的值,而不需要像 `class` 组件那么复杂的去使用。




---


对于上面这个功能来说,如果使用 `class` 组件来实现的话,**具体代码如下:**



import React from ‘react’

class ClickCounter extends React.Component {
constructor() {
super()

    // 定义 state
    this.state = {
        count: 0,
        name: '星期一研究室'
    }

    this.clickHandler = this.clickHandler.bind(this)
}
render() {
    return <div>
        <p>你点击了 {this.state.count} 次 {this.state.name}</p>
        <button onClick={this.clickHandler}>点击</button>
    </div>
}
clickHandler() {
    // 修改 state
    this.setState({
        count: this.state.count + 1,
        name: this.state.name + '2021'
    })
}

}

export default ClickCounter


大家可以看到,如果使用 `class` 组件来解决的话,那么需要先定义 `state` ,然后再定义一个函数,再使用 `setState` 才能去修改值,这样似乎还麻烦了点。


相信到这里,大家已经感受到 `hooks` 的快乐之处了。


下面,我们来总结关于 `useState` 的一些知识点。


#### (3)useState使用总结


* `useState(xxx)` 传入初始值,返回数组 `[state, setState]` ;
* 通过 `state` 获取值;
* 通过 `setState(xxx)` 修改值。


#### (4)Hooks命名规范


* 规定所有的 `Hooks` 都要使用 `use` 开头,如 `useXxx` ;
* 自定义 `Hook` 也要以 `use` 开头;
* 非 `Hooks` 的地方,尽量不要使用 `useXxx` 写法,不然容易造成误解。


### 2、Effect Hook🗞️


#### (1)让函数组件模拟生命周期


* 默认函数组件**没有生命周期**;
* 函数组件是一个**纯函数**,执行完即销毁,自己无法实现生命周期;
* 使用 `Effect Hook` 把生命周期 “钩” 到纯函数中。


#### (2)举例阐述


同样地,我们用于 `useState` 相同的例子,来体验下 `useEffect` 。


我们先在 `src|components` 下建立一个文件,命名为 `LiftCycles.js` 。 **具体代码如下:**



import React, { useState, useEffect } from ‘react’

function LifeCycles() {
const [count, setCount] = useState(0)
const [name, setName] = useState(‘星期一研究室’)

// 模拟 class 组件的 DidMount 和 DidUpdate
useEffect(() => {
    console.log('在此发送一个 ajax 请求')
})

function clickHandler() {
    setCount(count + 1)
    setName(name + '2020')
}

return <div>
    <p>你点击了 {count} 次 {name}</p>
    <button onClick={clickHandler}>点击</button>
</div>

}

export default LifeCycles


现在,我们在 `App.js` 中注册该组件。**具体代码如下:**



import React, { useState } from ‘react’;
import LifeCycles from ‘./components/LifeCycles’

function App() {
const [flag, setFlag] = useState(true)

return (
<div
{flag && }

);
}

export default App;


此时,**浏览器的显示效果如下:**


![useEffect①](https://img-blog.csdnimg.cn/fd64f75912774d10ba449f57a1e26298.gif#pic_center)


大家可以看到, `useEffect` 如果只传入一个函数的话,那么它模拟的是 `DidMount` 和 `DidUpdate` 这两个生命周期的功能。每当我们点击一次的时候,浏览器就会打印一次,也就是组件加载和组件更新是在一起进行的。




---


那如果我们想要让组件加载和组件更新分开实现呢,同样有办法。我们来改造下 `LiftCycles.js` 的代码。**具体代码如下:**



import React, { useState, useEffect } from ‘react’

function LifeCycles() {
const [count, setCount] = useState(0)
const [name, setName] = useState(‘星期一研究室’)

// 模拟 class 组件的 DidMount
useEffect(() => {
    console.log('加载完了')
}, []) // 第二个参数是 [] (不依赖于任何 state)

// 模拟 class 组件的 DidUpdate
useEffect(() => {
    console.log('更新了')
}, [count, name]) // 第二个参数就是依赖的 state

function clickHandler() {
    setCount(count + 1)
    setName(name + '2020')
}

return <div>
    <p>你点击了 {count} 次 {name}</p>
    <button onClick={clickHandler}>点击</button>
</div>

}

export default LifeCycles


此时浏览器的**显示效果如下:**


![useEffect②](https://img-blog.csdnimg.cn/6e5423f19b5147ab802be0e365f773fa.gif#pic_center)


大家可以看到,第一次的时候分别加载和更新了 `1` 次。等到我们去点击的时候,因为已经加载完了,所以这个时候就是更新了。


那我们来梳理一下, `useEffect` 在加载和更新的时候,分别是怎么进行处理的?


看上面的代码中我们可以发现,`useEffect` 还可以接收第二个参数,第二个参数如果空值,那么它不依赖于任何 `state` ,表示 `componentDidMount` 这个生命周期。相反,如果第二个参数**没有依赖值**或者**接收依赖于 state 的值**这两种情况时,那么它模拟 `componentDidUpdate` 这个生命周期。




---


说到这里,可能有的小伙伴还想问,那跟**销毁**相关的生命周期,又怎么处理呢?我们继续来对 `LiftCycles.js` 的代码进行改造。**具体如下:**



import React, { useState, useEffect } from ‘react’

function LifeCycles() {
const [count, setCount] = useState(0)
const [name, setName] = useState(‘星期一研究室’)

// 模拟 class 组件的 DidMount
useEffect(() => {
    let timerId = window.setInterval(() => {
        console.log(Date.now())
    }, 1000)

    // 返回一个函数
    // 模拟 WillUnMount
    return () => {
        window.clearInterval(timerId)
    }
}, [])

function clickHandler() {
    setCount(count + 1)
    setName(name + '2020')
}

return <div>
    <p>你点击了 {count} 次 {name}</p>
    <button onClick={clickHandler}>点击</button>
</div>

}

export default LifeCycles


大家可以看以上代码,在这里,我们通过 `return` 一个函数,去模拟 `componentWillUnMount` 这个生命周期,来销毁每一次定时器中执行的任务。


到这里,相信大家对 `useEffect` 已经有了一定的了解。现在,我们来对 `useEffect` 做个小结。


#### (3)useEffect使用总结


* 模拟 `componentDidMount - useEffect` 依赖 `[]` ;
* 模拟 `componentDidUpdate - useEffect` 无依赖,或者依赖 `[a, b]` ;
* 模拟 `componentWillUnMount - useEffect` 中**返回一个函数**。


#### (4)useEffect让纯函数有了副作用


* 默认情况下,执行纯函数的时候,只需要输入参数并返回结果即可,是没有任何副作用的;
* 所谓副作用,就是对函数之外造成影响,如**设置全局定时任务**;
* 而组件需要副作用,所以需要 `useEffect` “钩” 到纯函数中;
* 因此, `useEffect` 这个副作用并不是一件坏事。


#### (5)useEffect中返回函数 fn


有一种值得注意的情况是,在上面我们通过返回一个函数来模拟 `WillUnMount` ,但这个模拟后的结果还**不完全等于** `WillUnMount` 。现在,我们在 `src|components` 下建立一个文件,命名为 `FriendStatus.js` 。**具体代码如下:**



import React, { useState, useEffect } from ‘react’

function FriendStatus({ friendId }) {
const [status, setStatus] = useState(false)

// DidMount 和 DidUpdate
useEffect(() => {
    console.log(`开始监听 ${friendId} 在线状态`)

    // 【特别注意】
    // 此处并不完全等同于 WillUnMount
    // props 发生变化,即更新,也会执行结束监听
    // 准确的说:返回的函数,会在下一次 effect 执行之前,被执行
    return () => {
        console.log(`结束监听 ${friendId} 在线状态`)
    }
})

return <div>
    好友 {friendId} 在线状态:{status.toString()}
</div>

}

export default FriendStatus


`App.js` 的代码如下:



import React, { useState } from ‘react’;
import FriendStatus from ‘./components/FriendStatus’

function App() {
const [flag, setFlag] = useState(true)
const [id, setId] = useState(1)

return (



<button onClick={() => setFlag(false)}>flag = false
<button onClick={() => setId(id + 1)}>id++

  {flag && <FriendStatus friendId={id}/>}
</div>

);
}

export default App;


此时,**浏览器的显示效果如下:**


![useEffect③](https://img-blog.csdnimg.cn/28df613bb3c6432295c1d9cdb0f9ff18.gif#pic_center)


大家可以看到,当开始下一个监听时,会先结束掉上一个监听再开始下一个。正如图中所看到的,一开始我们正在监听 `id` 为 `1` 的好友,那当我们想要点击 `id++` 按钮去监听好友 `2` 时,`useEffect` 会先去结束掉 `1` 的状态,再让好友 `2` 上线。


此时,我们要注意的一个点是,执行结束监听的这个函数,执行的是 `DidUpdate` 生命周期,而不是 `WillUnMount` 生命周期。**函数**在这个时候是属于**更新状态**而不是**销毁状态**。


依据以上内容,我们来做个小结。**具体如下:**


* 当 `useEffect` 依赖于 `[]` 的时候,在组件销毁时执行 `return` 的函数 `fn` ,等于 `WillUnMount` 生命周期;
* 当 `useEffect` 无依赖或依赖于 `[a, b]` 的时候,组件是在更新时执行 `return` 的函数 `fn` ;即在下一次执行 `useEffect` 之前,就会先执行 `fn` ,此时模拟的是 `DidUpdate` 生命周期。


### 3、其他Hooks🗞️


上面我们讲了两个比较常用的 `hooks` → `useState` 和 `useEffect` 。接下来,我们来了解其他几个比较不常用的 `hooks` 。


#### (1)useRef


`Ref` 是用于对 **值的修改** 和 **DOM 元素的获取** 。**先来看一段代码:**



import React, { useRef, useEffect } from ‘react’

function UseRef() {
const btnRef = useRef(null) // 初始值

const numRef = useRef(0)
numRef.current = 2;

useEffect(() => {
    console.log(btnRef.current) // DOM 节点
    console.log(numRef.current); // 得到值
}, [])

return <div>
    <button ref={btnRef}>click</button>
</div>

}

export default UseRef


此时,**浏览器的显示效果为:**


![useRef](https://img-blog.csdnimg.cn/f9389c65be994a8e9e411ed679d7d75e.png#pic_center)


大家可以看到,如果将 `btnRef` 绑定到 `ref={btnRef}` 上,那么 `btnRef.current` 获取到的是当前的 `DOM` 节点。


另外一种情况是,大家定位到 `numRef` ,如果我们给其进行赋值并修改,那么 `numRef.current` 最终得到的值是修改后的值。


#### (2)useContext


很多时候,我们经常会有一些比较静态的属性需要做切换,比如:**主题颜色切换**。这个时候就需要用到 `context` 上下文来处理。那在 `hook` 中,就有 `useContext` 可以处理这件事情。先来看一段**演示代码:**



import React, { useContext } from ‘react’

// 主题颜色
const themes = {
light: {
foreground: ‘#000’,
background: ‘#eee’
},
dark: {
foreground: ‘#fff’,
background: ‘#222’
}
}

// 创建 Context
const ThemeContext = React.createContext(themes.light) // 初始值

function ThemeButton() {
const theme = useContext(ThemeContext)

return <button style={{ background: theme.background, color: theme.foreground }}>
    hello world
</button>

}

function Toolbar() {
return




}

function App() {
return <ThemeContext.Provider value={themes.dark}>

</ThemeContext.Provider>
}

export default App


此时浏览器的**显示效果如下:**


![useContext](https://img-blog.csdnimg.cn/b16e2d089ee949d7b343235548a51bb8.png#pic_center)


现在属于**黑色背景**的主题。如果我们要切换为**白色背景**的主题,那么只需要把最底下的代码 `value={themes.dark}` 改为 `value={themes.light}` 即可。


#### (3)useReducer


在 `redux` 中,我们会用到 `reducer` ,但 `useReducer` 跟 `redux` 还有一点区别。 `useReducer` 是对单个组件进行状态


**先来看一段代码:**



import React, { useReducer } from ‘react’

const initialState = { count: 0 }

const reducer = (state, action) => {
switch (action.type) {
case ‘increment’:
return { count: state.count + 1 }
case ‘decrement’:
return { count: state.count - 1 }
default:
return state
}
}

function App() {
// 很像 const [count, setCount] = useState(0)
const [state, dispatch] = useReducer(reducer, initialState)

return <div>
    count: {state.count}
    <button onClick={() => dispatch({ type: 'increment' })}>increment</button>
    <button onClick={() => dispatch({ type: 'decrement' })}>decrement</button>
</div>

}

export default App


此时浏览器的**显示效果如下:**


![useReducer](https://img-blog.csdnimg.cn/3bb32006d3ad47dc9b6e5642a3014ac2.gif#pic_center)


我们将要改变的值放到 `reducer` 当中,之后再将 `reducer` 传递给 `useRouter` 。最后,通过 `dispatch` 来对值进行绑定。


下面我们来梳理一下 `useRuducer` 和 `redux` 的区别:


* `useReducer` 是 `useState` 的代替方案,用于处理 `state` 的复杂变化;
* `useReducer` 是**单个组件状态管理**,组件通讯还需要 `props` ;
* `redux` 是全局的**状态管理**,**多组件共享数据**。


#### (4)useMemo


`useMemo` 是 `hooks` 中性能优化的一部分。当我们不使用 `useMemo` 时,状态时这样的。**看以下这段代码:**



import React, { useState } from ‘react’

// 子组件
function Child({ userInfo }) {
console.log(‘Child render…’, userInfo)

return <div>
    <p>This is Child {userInfo.name} {userInfo.age}</p>
</div>

}

// 父组件
function App() {
console.log(‘Parent render…’)

const [count, setCount] = useState(0)
const [name, setName] = useState('星期一研究室')

const userInfo = { name, age: 20 }

return <div>
    <p>
        count is {count}
        <button onClick={() => setCount(count + 1)}>click</button>
    </p>
    <Child userInfo={userInfo}></Child>
</div>

}

export default App


此时,控制台的**打印效果如下:**


![useMemo①](https://img-blog.csdnimg.cn/31ed3c2516584f2a970c008f6977fdd1.gif#pic_center)


大家可以看到,每每我们点击一次,不管 `state` 的值是否更新时,子组件 `Child` 都会重新打印一次。 这对于程序来说,是比较耗费性能的。因此,我们要用 `useMemo` 来阻止 `Child` 事件频繁打印,提高程序的性能。**代码改造如下:**



import React, { useState, memo, useMemo } from ‘react’

// 子组件
// 类似 class PureComponent ,对 props 进行浅层比较
const Child = memo(({ userInfo }) => {
console.log(‘Child render…’, userInfo)

return <div>
    <p>This is Child {userInfo.name} {userInfo.age}</p>
</div>

})

// 父组件
function App() {
console.log(‘Parent render…’)

const [count, setCount] = useState(0)
const [name, setName] = useState('星期一研究室')

// 用 useMemo 缓存数据,依赖于 [name] 
// 当name有更新时,{ name, age: 18 } 这个缓存就会失效
const userInfo = useMemo(() => {
    return { name, age: 18 }
}, [name])

return <div>
    <p>
        count is {count}
        <button onClick={() => setCount(count + 1)}>click</button>
    </p>
    <Child userInfo={userInfo}></Child>
</div>

}

export default App


此时,浏览器的**显示效果如下:**


![useMemo②](https://img-blog.csdnimg.cn/5bff530ab3374dc8823bf60966513aa7.gif#pic_center)


大家可以看到, `Child` 组件除了第一次更新有打印之外,之后的没有更新就不会再进行打印。那它是怎么使用的呢,首先,我们要用 `memo` 把子组件给包裹下来,之后呢,通过 `useMemo` 去缓存数据,同时这个数据要依赖于 `[name]` ;值得注意的是,如果不依赖于 `[name]` ,它是不会生效的。


现在,我们来对 `useMemo` 做个总结,**具体如下:**


* `React` 默认会更新**所有子组件**;
* `class` 组件使用 `shouldComponentUpdate` 和 `PureComponent` 做优化;
* `Hooks` 中使用 `useMemo` 做优化,但优化原理和 `class` 组件是相同的。


#### (5)useCallback


上面我们说到的是使用 `useMemo` 来**缓存数据**,现在我们来讲下 `useCallback` 。 `useCallback` 主要是用来**缓存函数**。


假设我们现在不使用 `useCallback` ,来运行**下面这段代码:**



import React, { useState, memo, useMemo, useCallback } from ‘react’

// 子组件,memo 相当于 PureComponent
const Child = memo(({ userInfo, onChange }) => {
console.log(‘Child render…’, userInfo)

return <div>
    <p>This is Child {userInfo.name} {userInfo.age}</p>
    <input onChange={onChange}></input>
</div>

})

// 父组件
function App() {
console.log(‘Parent render…’)

const [count, setCount] = useState(0)
const [name, setName] = useState('星期一研究室')

// 用 useMemo 缓存数据
const userInfo = useMemo(() => {
    return { name, age: 21 }
}, [name])

function onChange(e) {
    console.log(e.target.value)
}

return <div>
    <p>
        count is {count}
        <button onClick={() => setCount(count + 1)}>click</button>
    </p>
    <Child userInfo={userInfo} onChange={onChange}></Child>
</div>

}

export default App


此时浏览器的打印效果如下:


![useCallback①](https://img-blog.csdnimg.cn/5708c417b4d84450af8ac7061671503b.gif#pic_center)


大家可以看到,如果没有使用 `useCallback` ,那么其会一直将子组件打印出来,也就是 `onChange` 事件会一直运转。现在,我们将 `onChange` 事件改造一下,**具体如下:**



// 用 useCallback 缓存函数
const onChange = useCallback(e => {
console.log(e.target.value)
}, [])


此时我们来看下浏览器运行的效果:


![useCallback②](https://img-blog.csdnimg.cn/dad9d695249c44a28aea2856054596b1.gif#pic_center)


大家可以看到,加上 `useCallback` 之后,且 `Child` 没有更新时,也就不会再更新啦!


接下来我们对 `useMemo` 和 `useCallback` 做个小结:


* `useMemo` 缓存数据;
* `useCallback` 缓存函数;
* 两者都是 `React Hooks` 的常见优化策略。


### 4、自定义Hook🗞️


#### (1)为什么要使用自定义Hook


* 用来封装**通用的功能**;
* 可以**开发**和**使用**第三方 `Hooks` ;
* 自定义 `Hook` 带来了无限的扩展性,解耦代码。


#### (2)举例阐述


假设我们现在想要封装一个 `useAxios` ,那怎么实现呢?


首先我们需要先在项目中安装 `axios` ,**具体代码如下:**



npm i axios --save


接着,我们在项目的 `src|customHooks` 文件夹下新建一个文件,命名为 `useAxios.js` 。**具体代码如下:**



import { useState, useEffect } from ‘react’
import axios from ‘axios’

// 封装 axios 发送网络请求的自定义 Hook
function useAxios(url) {
// loading 模拟当前是否再等待中
const [loading, setLoading] = useState(false)
// 请求成功时返回的数据
const [data, setData] = useState()
// 请求失败时返回的一些信息
const [error, setError] = useState()

useEffect(() => {
    // 利用 axios 发送网络请求
    setLoading(true)
    axios.get(url) // 发送一个 get 请求
        .then(res => setData(res))
        .catch(err => setError(err))
        .finally(() => setLoading(false))
}, [url])

return [loading, data, error]

}

export default useAxios


继续,我们在项目的 `src|components` 文件夹,新建一个文件,命名为 `CustomHookUsage.js` 。这个组件主要用来使用上面所自定义的 `useAxios` 这个 `hook` 。**具体代码如下:**



import React from ‘react’
import useAxios from ‘…/customHooks/useAxios’

function App() {
const url = ‘http://localhost:3000/’
// 数组解构
const [loading, data, error] = useAxios(url)

if (loading) return <div>loading...</div>

return error
    ? <div>{JSON.stringify(error)}</div>
    : <div>{JSON.stringify(data)}</div>

}

export default App


最后,我们在项目的 `App.js` 中来使用它。**具体代码如下:**



import React, { useState } from ‘react’;
import CustomHookUsage from ‘./components/CustomHookUsage’

function App() {

return (


{}

);
}

export default App;


此时,我们来看下浏览器的显示效果:


![useAxios](https://img-blog.csdnimg.cn/4feacd5e0f274b3ea6040e32913f8d4d.gif#pic_center)


大家可以看到,首先是在等待的时候,它会先出现 `loading` 。之后呢,如果在等待结束并请求成功后,会返回 `data` 。当然,我们这里没有演示 `error` 的情况。大家可以把 `url` 修改为不存在的请求地址,即可测试 `error` 的情况。


#### (3)总结


![img](https://img-blog.csdnimg.cn/img_convert/54bcfd9b8812ff1be895a0b5a58426f9.png)
![img](https://img-blog.csdnimg.cn/img_convert/4182722984f109c2b45b819049189eab.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

JSON.stringify(error)}</div>
        : <div>{JSON.stringify(data)}</div>
}

export default App


最后,我们在项目的 App.js 中来使用它。具体代码如下:

import React, { useState } from 'react';
import CustomHookUsage from './components/CustomHookUsage'

function App() {

  return (
    <div>
      {<CustomHookUsage/>}
    </div>
  );
}

export default App;


此时,我们来看下浏览器的显示效果:

useAxios

大家可以看到,首先是在等待的时候,它会先出现 loading 。之后呢,如果在等待结束并请求成功后,会返回 data 。当然,我们这里没有演示 error 的情况。大家可以把 url 修改为不存在的请求地址,即可测试 error 的情况。

(3)总结

[外链图片转存中…(img-CTccA2EG-1715876482198)]
[外链图片转存中…(img-IWYr7lSN-1715876482198)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值