class组件存在哪些问题
- 大型组件很难拆分和重构,很难测试(即class不易拆分)
- 相同业务逻辑,分散到各个方法中,逻辑混乱
- 复用逻辑变的复杂,如mixins、HOC、Render Props
React提倡函数式编程,view = fn(props)
函数更灵活,更容易拆分,更容易测试
但是函数组件太简单,需要增强能力 —— Hooks
Hooks命名规范
- 规定所有的Hooks都用use开发
- 自定义Hook也要以use开头
- 非Hooks的地方,尽量不要使用useXxx写法
State Hook
为什么要有Hooks
- 默认函数组件没有state
- 函数组件是一个纯函数,执行完即销毁,无法存储state
- 需要State Hook,即把state“钩”到纯函数中
import React, {
useState } from 'react'
// 数组的解构
// useState 就是一个 Hook “钩”,最基本的一个 Hook
const [count, setCount] = useState(0) // 传入一个初始值
const [name, setName] = useState('双越老师')
// const arr = useState(0)
// const count = arr[0]
// const setCount = arr[1]
function clickHandler() {
setCount(count + 1)
setName(name + '2020')
}
return <div>
<p>你点击了 {
count} 次 {
name}</p>
<button onClick={
clickHandler}>点击</button>
</div>
使用总结
- useState(0)传入初始值,返回数组[state, setState]
- 通过state获取值
- 通过setState(1)修改
Effect Hook
让函数组件模拟生命周期
- 函数组件没有生命周期
- 函数组件时一个纯函数,执行完即销毁,自己无法实现生命周期
- 使用Effect Hooks把生命周期“钩”到函数中
import React, {
useState, useRef, useEffect } from 'react'
function UseEffectChangeState() {
const [count, setCount] = useState(0)
// 模拟 DidMount
const countRef = useRef(0)
useEffect(() => {
console.log('useEffect...', count)
// 定时任务
const timer = setInterval(() => {
console.log('setInterval...', countRef.current)
// setCount(count + 1)
setCount(++countRef.current)
}, 1000)
// 清除定时任务
return () => clearTimeout(timer)
}, []) // 依赖为 []
// 依赖为 [] 时: re-render 不会重新执行 effect 函数
// 没有依赖:re-render 会重新执行 effect 函数
return <div>count: {
count}</div>
}
export default UseEffectChangeState
useEffect让纯函数有了副作用
- 默认情况下,执行纯函数,输入参数,返回结果,无副作用
- 所谓副作用,就是对函数之外造成影响,如设置全局定时任务
- 而组件需要副作用,所以需要useEffect“钩”到纯函数中
hooks写法:
import React, {
useState, useEffect } from 'react'
function FriendStatus({
friendId }) {
const [status, setStatus] = useState(false)
// DidMount 和 DidUpdate
useEffect(() => {
console.log(`开始监听 ${
friendId} 在线状态`)
// 【特别注意】
// 此处并不完全等同于 WillUnMount
// props 发生变化,即更新,也会执行结束监听
// 准确的说:返回的函数,会在下一次 effect 执行之前,被执行
return () => {
console.log(`结束监听 ${
friendId} 在线状态`)
}
})
return <div>
好友 {
friendId} 在线状态:{
status.toString()}
</div>
}
export default FriendStatus
class:
import React from 'react'
class FriendStatus extends React.Component {
constructor(props) {
super(props)
this.state = {
status: false // 默认当前不在线
}
}
render() {
return