持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第33天,点击查看活动详情
前言,hooks的出现是为了弥补function与class组件都不能解决的问题。
functionUI组件存在问题:
- 纯函数,没有状态
- 没有生命周期
- 没有this问题
class容器组件存在问题:
- this指向问题
- 生命周期复杂 + 性能差 + 版本问题
- 相同的逻辑 分散到不同的生命周期 + 维护困难
- 复用能力差:高阶组件 增加组件层级 臃肿;
hooks的出现是一个新特性,它可以说是function组件的增强,增强使其具备类组件的功能,变成特殊的函数,最终成为hooks钩子函数。
hooks增强的方向有几块:
- 使函数组件內部可以存储状态
- 副作用操作
- 性能优化(缓存等)
常见的hooks:
useState状态
useEffect副作用
useMemo 处理缓存
useRef 处理dom
useCallback 性能优化
自定义hooks:useImperativeHandle子组件暴露指令方法;
useLayoutEffect处理浏览器渲染之前执行.....
useState
回顾:react语法本质上是jsx语言,首先准备app容器,引用三个语法库巴拉巴拉和之前一样,不多说了。
在使用类组件时的代码👇,来更新count
class App extends React.Component{
state={count:0}
render(){
return(
<div>
<button onClick={()=>{
this.setState({count:this.state.count+1})
}}>click</button>
</div>
)
}
}
复制代码
第二种方法,使用useState通过函数组件来达成一样的效果:
先从react中解构出钩子函数:
const {Component,useState} = React
复制代码
使用钩子函数时注意:
- 在函数组件中,直接用useState声明
- useState()中的唯一参数代表初始化的state默认值
- 它的返回值是一个数组
[初始状态,改变状态的方法],其中初始状态可以是普通的数据类型,也可以是复杂的数据类型 - 读取状态的时候直接{state}就可以获取到
使用:
const {Component,useState} = React //解构出来
function App(){
const [count,setCount] = useState(0) //写好函数及其返回值
console.log("render");
return(
<div>
<h1>{count}</h1> //直接获取状态
<button onClick={()=>{
setCount(count+1) //直接调用函数去改变状态
}}>click</button>
</div>
)
}
复制代码
且在函数组件中每点击一次,虽没有render(){}钩子函数,但函数组件本身就相当于render了。以至于每点击一次就会触发一次render。
本质
当useState时,就相当于內部有一个数组,且数组的第一位被赋值了。
const arrVarible = useState(0); //0为变量默认值
console.log(arrVarible,"arrVarible");
//数组解构的本质
const count = arrVarible[0]; // 变量
const setCount = arrVarible[1]; //改变变量的函数函数
复制代码
参数不止可以被设置为数字,也可以将变量设置成一个复杂类型的数据👇
console.log("initCount初始化");
let initCount = 0;
for (let i = 0; i < 1000; i++) {
initCount+=1;
console.log(i);
}
const [count,setCount] = useState(initCount)
复制代码
如上代码,是将for循环执行完才去render代码。并且每点击一次去改变count变量,都会重新从1到1000.这属实是很浪费性能。我们只需要让for循环只在初始执行一次即可,接下来就依赖它的值进行累加,这就是我们要的结果。于是引出概念---惰性初始化。
即,实现for循环只在初始时执行一次。
const [count,setCount] = useState(()=>{
//惰性初始化,第一次会执行,useState中的函数只会执行一次,且自动
console.log("initCount初始化");
let initCount = 365*24;
return(
initCount
)
})
复制代码
方法:在useState內部设置一个箭头函数,直接成为初始值,实现自动执行一次的需求。