useState

136 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第33天,点击查看活动详情

前言,hooks的出现是为了弥补function与class组件都不能解决的问题。

functionUI组件存在问题:

  1. 纯函数,没有状态
  2. 没有生命周期
  3. 没有this问题

class容器组件存在问题:

  1. this指向问题
  2. 生命周期复杂 + 性能差 + 版本问题
  3. 相同的逻辑 分散到不同的生命周期 + 维护困难
  4. 复用能力差:高阶组件 增加组件层级 臃肿;

hooks的出现是一个新特性,它可以说是function组件的增强,增强使其具备类组件的功能,变成特殊的函数,最终成为hooks钩子函数。

hooks增强的方向有几块:

  1. 使函数组件內部可以存储状态
  2. 副作用操作
  3. 性能优化(缓存等)

常见的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
复制代码

使用钩子函数时注意:

  1. 在函数组件中,直接用useState声明
  2. useState()中的唯一参数代表初始化的state默认值
  3. 它的返回值是一个数组[初始状态,改变状态的方法],其中初始状态可以是普通的数据类型,也可以是复杂的数据类型
  4. 读取状态的时候直接{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。

image.png

本质

当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)
复制代码

image.png

如上代码,是将for循环执行完才去render代码。并且每点击一次去改变count变量,都会重新从1到1000.这属实是很浪费性能。我们只需要让for循环只在初始执行一次即可,接下来就依赖它的值进行累加,这就是我们要的结果。于是引出概念---惰性初始化

即,实现for循环只在初始时执行一次。

const [count,setCount] = useState(()=>{
                //惰性初始化,第一次会执行,useState中的函数只会执行一次,且自动
                console.log("initCount初始化");
                let initCount = 365*24;
                return(
                    initCount
                )
            })
复制代码

方法:在useState內部设置一个箭头函数,直接成为初始值,实现自动执行一次的需求。