React hooks 是什么?
React hooks是React 16.8 中引入到新功能,帮助开发者仅仅通过函数组件就可以使用原本Class组件才具备的state等功能。React hooks通过一系列函数式的Api实现上述功能,其中最常用的有useState、useEffect、useContext等。
本文首先通过一个小例子先介绍一下useState:
类组件示例
React中当我们需要组件管理内部状态时,我们需要将其定义为类组件
import React from 'react'
import './styles.css'
// 1...10的随机数作为 count初始值
const intialState = Math.floor(Math.random() * 10) + 1
class Counter extends React.Component {
constructor(props) {
super(props)
this.state = {
count: intialState,
open: true
}
}
// toggle方法用来更新state
toggle = () => {
this.setState({ open: !this.state.open })
}
render() {
return (
<>
<button onClick={this.toggle}>
{this.state.open ? 'close' : 'open'}
</button>
<!-- state.open 控制div的显示与否 -->
<div className={this.state.open ? 'isOpen' : 'isClose'}>
<p>Count: {this.state.count} </p>
<!-- 点击按钮后 count++ -->
<button
onClick={() => this.setState({ count: this.state.count + 1 })}
>
+ 1
</button>
<!-- 点击按钮后 count-- -->
<button
onClick={() => this.setState({ count: this.state.count - 1 })}
>
- 1
</button>
<button onClick={() => this.setState({ count: 0 })}>0</button>
<button onClick={() => this.setState({ count: intialState })}>
Reset
</button>
</div>
</>
)
}
}
export default Counter
CSS定义显示/隐藏的style
.isClose {
display: none;
}
.isOpen {
display: block;
}
通过React hooks改造为函数组件
通过useState可以将上述类组件的实现改造为函数组件,首先定义函数组件如下:
const ExComponent = props => {
// todo: 使用hooks
return <div />
}
通过useState可以帮助我们在函数式组件中声明state,
// useState声明state
const [count, setCount] = useState(intialState)
// 类组件声明state
this.state = {
count: intialState
}
useState通过参数设置初始值,通过解构useState返回的数组可以获得两个值:
- state的当前值
- state更新函数
state的更新必须通过更新函数进行,不能直接修改当前值。
在函数组件中插入useState来实现状态管理:
// 引入useState
import React, { useState } from 'react'
import './styles.css'
const Counter = () => {
const intialState = Math.floor(Math.random() * 10) + 1
// 多个state需要通过useState分别声明,并设置初始值
const [count, setCount] = useState(intialState)
const [open, setOpen] = useState(true)
const toggle = () => setOpen(!open) //通过更新函数更新state
return (
<>
<button onClick={toggle}>{open ? 'close' : 'open'}</button>
<div className={open ? 'isOpen' : 'isClose'}>
<p>Count :{count}</p>
<!-- 通过更新函数更新state -->
<button onClick={() => setCount(prevState => prevState + 1)}>
+ 1
</button>
<button onClick={() => setCount(count - 1)}>- 1</button>
<button onClick={() => setCount(0)}>0</button>
<button onClick={() => setCount(intialState)}>Reset</button>
</div>
</>
)
}
export default Counter
setCount的变更会造成函数组件的重绘,重绘时虽然重新执行useState(...),但是state的值会保持最新状态,并不会被reset为初始值。