前言
博主主页蜡笔雏田学代码
专栏链接React专栏
今天来学习下react中非常重要的一个知识:Hooks
感兴趣的小伙伴一起来看看吧~
文章图片
文章目录
- Hooks概念理解
-
- 1. 什么是hooks
- 2. Hooks解决了什么问题
- useState
-
- 1. 基础使用
-
- 作用
- 使用步骤
- 代码实现
- 2. 状态的读取和修改
-
- 读取状态
- 修改状态
- 3. 组件的更新过程
- 4. 使用规则
- useEffect
-
- 1. 理解函数副作用
-
- 什么是副作用
- 常见的副作用
- 2. 基础使用
-
- 作用
- 使用步骤
- 3. 依赖项控制执行时机
-
- 不添加依赖项
- 添加空数组
- 添加特定依赖项
- 清理副作用
- 阶段小练习 - 自定义hook
Hooks概念理解 1. 什么是hooks
Hooks的本质:一套能够使函数组件更强大,更灵活的“钩子”React体系里组件分为
类组件
和 函数组件
【React|【React-Hooks基础】入门级详解——useState / useEffect /自定义hook】经过多年的实战,函数组件是一个更加匹配React的设计理念
UI = f(data)
,也更有利于逻辑拆分与重用的组件表达形式,而先前的函数组件是不可以有自己的状态的,为了能让函数组件可以拥有自己的状态,所以从react v16.8开始,Hooks应运而生.注意点:
2. Hooks解决了什么问题
- 有了hooks之后,为了兼容老版本,class类组件并没有被移除,俩者都可以使用
- 有了hooks之后,不能再把函数成为无状态组件了,因为hooks为函数组件提供了状态
- hooks只能在函数组件中使用
Hooks的出现解决了俩个问题 : 1. 组件的状态逻辑复用 2.class组件自身的问题
组件的逻辑复用
在hooks出现之前,react先后尝试了 mixins混入,HOC高阶组件,render-props等模式
但是都有各自的问题,比如mixin的数据来源不清晰,高阶组件的嵌套问题等等
class组件自身的问题
class组件就像一个厚重的‘战舰’ 一样,大而全,提供了很多东西,有不可忽视的学习成本,比如各种生命周期,this指向问题等等,而我们更多时候需要的是一个轻快灵活的’快艇’
useState 1. 基础使用 作用
使用步骤useState为函数组件提供状态(state)
- 导入
useState
函数 - 调用
useState
函数,并传入状态的初始值 - 从
useState
函数的返回值中,拿到状态和修改状态的方法 - 在JSX中展示状态
- 调用修改状态的方法更新状态
import { useState } from 'react'function App() {
// 参数:状态初始值,比如,传入 0 表示该状态的初始值为 0
// 返回值:数组,包含两个值:1.状态值(state) 2.修改该状态的函数(setState)
const [count, setCount] = useState(0)
return (
)
}
export default App
2. 状态的读取和修改 读取状态
该方式提供的状态,是函数内部的局部变量,可以在函数内的任意位置使用修改状态
- setCount是一个函数,参数表示
最新的状态值
- 调用该函数后,将使用新值替换旧值
- 修改状态后,由于状态发生变化,会引起视图变化
注意事项
修改状态的时候,一定要使用新的状态替换旧的状态,不能直接修改旧的状态,尤其是引用类型3. 组件的更新过程 函数组件使用 useState hook 后的执行过程,以及状态值的变化
组件第一次渲染
- 从头开始执行该组件中的代码逻辑
- 调用
useState(0)
将传入的参数作为状态初始值,即:0 - 渲染组件,此时,获取到的状态 count 值为: 0
组件第二次渲染
- 点击按钮,调用
setCount(count + 1)
修改状态,因为状态发生改变,所以,该组件会重新渲染 - 组件重新渲染时,会再次执行该组件中的代码逻辑
- 再次调用
useState(0)
,此时 React 内部会拿到最新的状态值而非初始值,比如,该案例中最新的状态值为 1 - 再次渲染组件,此时,获取到的状态 count 值为:1
注意:useState 的初始值(参数)只会在组件第一次渲染时生效。也就是说,以后的每次渲染,useState 获取到都是最新的状态值,React 组件会记住每次最新的状态值4. 使用规则
useState
函数可以执行多次,每次执行互相独立,每调用一次为函数组件提供一个状态function List(){
// 以字符串为初始值
const [name, setName] = useState('cp')
// 以数组为初始值
const [list,setList] = useState([])
}
useState
注意事项- 只能出现在函数组件或者其他hook函数中
- 不能嵌套在if/for/其它函数中, 只能写在函数组件的最外层(react按照hooks的调用顺序识别每一个hook)
let num = 1
function List(){
num++
if(num / 2 === 0){
const [name, setName] = useState('cp')
}
const [list,setList] = useState([])
}
// 俩个hook的顺序不是固定的,这是不可以的!!!
- 可以通过开发者工具查看hooks状态
副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)常见的副作用
- 数据请求 ajax发送
- 手动修改dom
- localstorage操作
useEffect函数的作用就是为react函数组件提供副作用处理的!
2. 基础使用 作用
为react函数组件提供副作用处理使用步骤
- 导入
useEffect
函数 - 调用
useEffect
函数,并传入回调函数 - 在回调函数中编写副作用处理(dom操作)
- 修改数据状态
- 检测副作用是否生效
组件首次渲染执行一次
,以及不管是哪个状态更改引起组件更新时都会重新执行
- 组件初始渲染
- 组件更新 (不管是哪个状态引起的更新)
useEffect(()=>{
console.log('副作用执行了')
})
添加空数组
组件只在首次渲染时执行一次
useEffect(()=>{
console.log('副作用执行了')
},[])
添加特定依赖项
副作用函数在首次渲染时执行
,在依赖项发生变化时重新执行
function App() {
const [count, setCount] = useState(0)
const [name, setName] = useState('zs') useEffect(() => {
console.log('副作用执行了')
}, [count])return (
<>
>
)
}
注意事项
useEffect 回调函数中用到的数据(比如,count)就是依赖数据,就应该出现在依赖项数组中,如果不添加依赖项就会有bug出现清理副作用
某种意义上 hook的出现 就是想不用生命周期概念也可以写业务代码
如果想要清理副作用 可以在副作用函数中的末尾return一个新的函数
,在新的函数中编写清理副作用的逻辑
注意执行时机为:
组件卸载时自动执行
- 组件更新时,下一个useEffect副作用函数执行之前自动执行
import { useEffect, useState } from "react"const App = () => {
const [count, setCount] = useState(0)
useEffect(() => {
const timerId = setInterval(() => {
setCount(count + 1)
}, 1000)
return () => {
// 用来清理副作用的事情
clearInterval(timerId)
}
}, [count])
return (
{count}
)
}export default App
阶段小练习 - 自定义hook 1??需求描述:自定义一个hook函数,实现获取滚动距离Y
const [y] = useWindowScroll()
import { useState } from "react"export function useWindowScroll () {
const [y, setY] = useState(0)
window.addEventListener('scroll', () => {
const h = document.documentElement.scrollTop
setY(h)
})
return [y]
}
2??需求描述: 自定义hook函数,可以自动同步到本地LocalStorage
const [message, setMessage] = useLocalStorage(key,defaultValue)
- message可以通过自定义传入默认初始值
- 每次修改message数据的时候 都会自动往本地同步一份
import { useEffect, useState } from 'react'export function useLocalStorage (key, defaultValue) {
const [message, setMessage] = useState(defaultValue)
// 每次只要message变化 就会自动同步到本地ls
useEffect(() => {
window.localStorage.setItem(key, message)
}, [message, key])
return [message, setMessage]
}
今天的分享就到这里啦? \textcolor{red}{今天的分享就到这里啦?} 今天的分享就到这里啦?
原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下
点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!
??收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!
??评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!
推荐阅读
- React|【Redux】如何实现多组件数据共享
- React|<react求和案例>react-redux基本使用与优化——Provider/mapDispatch
- js|chrome 插件开发指南
- 前端|Vue电商项目实战(三)
- Node.js|【Node.js】Express
- 【前端可视化】|echarts使用结合时间轴timeline动态刷新案例
- 笔记|TypeScript简记(一)
- React报错之useNavigate() may be used only in context of Router
- DGIOT支持工业设备租赁以及远程管控