当我们使用react框架时,有状态组件(Class)为我们提供了很多的声明周期,让我们能够处理不同的事件,但在大型项目中使用react时,就会发现,有状态组件冗长且难以复用,而react hooks的出现本质上时把这种面向生命周期编程变为面向业务逻辑编程,不用再去关心生命周期。
首先看一个简单的react
class Info extends React.Component {
constructor() {
super()
this.state = {
count: 0
}
}
render() {
return <div>
<p>your count{this.state.count}</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}></button>
</div>
}
}
使用hooks之后
import { useSate } from 'react'
function Info() {
const [count, setCount] = useSate(0)//0为count初始值
return <div>
<p>your count{count}</p>
<button onClick={() => this.setCount(count+1)}></button>
</div>
}
使用hooks之后,代码变得简洁,作为函数Info拥有了自己的状态Count,同时可以调用setCount更新自己的状态,这个hook让函数变为有状态函数,这就是第一个hook
useState
使用useState,需要传入一个参数作为状态的初始值,当函数执行后会返回两个值,一个是当前状态的属性,一个是修改状态的方法,其原理如下:
let _state; //将状态存储起来,防止状态重置
function useState(initialValue){
_state=_state||initialValue //第一次执行没有_state
function setState(newState){
_state=newState //修改状态
render()
}
return [_state,setState]
}
注如果state是一个对象,setState是不能部分更新的,setState不会帮我们合并属性,所以你需要自己手动合并
import {useSate} from 'react'
function Person(){
const [person,setPerson]=useSate({name:'Lucy',age:19})
const touch=()=>{
setPerson({
...person,//拷贝之前的所有属性
name:"jack" //覆盖之前的name属性
})
}
return <button onClick={touch}></button>
}
useState每次执行会返回一个新的state,setState会调用render()触发UI更新,由于更新是异步任务,所以setState也是异步任务,解决办法,结合另一个hook
useEffect
这个hook可以在函数式组件中执行副作用操作(数据获取,数据订阅,以及手动更改React组建中的DOM)。
useEffect拥有两个参数
(1)第一个参数为一个函数
这个函数就是为了告诉react组件需要在渲染后执行哪些操作,useEffect默认每次渲染后都会执行。但是也可以手动控制他的执行
(2)第二个参数为一个数组
当数组中的任意一项变化的时候,useEffect会被重新执行,如果传递一个空数组[],告诉useEffect不依赖与任意值,只执行一次