React Hooks?
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
使用过React的兄弟们都知道,在React中有两种组件:函数式组件
和类组件
。在React16.8之前,函数式组件是不能玩ref
和state
的,就连生命周期
都不能使用,最主要的原因是函数式组件没有this这个概念,而state、ref、生命周期函数等都是挂载在组件自身上。所以很多人选择使用类组件。而React16.8新增的Hooks就是为了增强函数式组件,引入了一系列的Hooks来完善函数式组件的功能。
有哪些Hooks,怎么使用?
在这里例举一些常用的Hooks,其他Hooks可以查看React中文文档。
React Hooks 都以use开头,Hook 本质就是 JavaScript 函数。
1 > useState -> state hook
state
是React组件的一个重要属性,用于记录状态,使用setState
方法更新state和视图。
我们先看一下在类组件中如何使用state:
类组件中使用
import React, { Component } from 'react'
export default class RClassComp extends Component {
state = {
account: '',
age: 0
}
handleClick = () => {
this.setState({
account: 'CoCoyY1',
age: 18
});
}
render() {
return (
<>
<div>姓名:{this.state.account}</div>
<div>年龄:{this.state.age}</div>
<button onClick={this.handleClick}>点我</button>
</>
)
}
}
复制代码
效果图:
在函数式组件中使用state:
使用useState
这一个Hook可以让我们在函数式组件中使用state,useState
方法接收一个初始值,返回一个数组,数组第一项为state,第二项为该state的set方法。
在函数式组件中使用
import React, { useState } from 'react';
export default () => {
const [obj, setObj] = useState({account: '', age: 0});
const handleClick = () => {
setObj({
account: 'CoCoyY1',
age: 18
});
}
return (
<>
<div>----RFC----</div>
<div>姓名:{obj.account}</div>
<div>年龄:{obj.age}</div>
<button onClick={handleClick}>点我</button>
</>
)
}
复制代码
效果图:
2 > useRef -> ref hook
ref
属性用来准确获取一个组件或元素的节点,虽然react官方不推荐大量使用,但还是非常常用的一个属性。
在类组件中使用ref:
类组件中有三种使用ref的方式:
(1)使用字符串;
(2)使用箭头函数(本人常用);
(3)使用createRef方法; -> 此方法取值时需要取
current
属性;
类组件中
import React, { Component } from 'react'
export default class RClassComp extends Component {
state = {
account: '',
age: 0
}
handleClick = () => {
const accountValue = this.inputEl.value;
this.setState({
account: accountValue,
age: 18
});
}
render() {
return (
<>
<div>姓名:{this.state.account}</div>
<div>
<input ref={c => this.inputEl = c} type="text" />
</div>
<div>年龄:{this.state.age}</div>
<button onClick={this.handleClick}>点我</button>
</>
)
}
}
复制代码
效果图:
在函数式组件中使用ref:
使用useRef
这一Hook可以让我们在函数式组件中使用ref,使用方法和类组件中createRef方法有点类似。
函数式组件
import React, { useState, useRef } from 'react';
export default () => {
const [obj, setObj] = useState({account: '', age: 0});
const inputEl = useRef();
const handleClick = () => {
const accountValue = inputEl.current.value;
setObj({
account: accountValue,
age: 18
});
}
return (
<>
<div>----RFC----</div>
<div>姓名:{obj.account}</div>
<div>
<input ref={inputEl} type="text" />
</div>
<div>年龄:{obj.age}</div>
<button onClick={handleClick}>点我</button>
</>
)
}
复制代码
效果图:
3 > useEffect -> 函数式组件的生命周期
在具体的项目中,我们会经常用到生命周期函数来发送请求或者是设置一些监听内容。
常用的生命周期函数
有:
(1)componentDidMount;
(2)componentDidUpdate;
(3)componentWillUnmount;
在类组件中使用生命周期函数:
类组件中
import React, { Component } from 'react'
export default class RClassComp extends Component {
state = {
count: 0,
}
componentDidMount() {
this.timer = setInterval(() => {
this.setState((state) => ({count: state.count + 1}));
}, 1000);
};
componentDidUpdate(preProps, preState) {
if(preState.count >= 5) {
this.setState({count: 0});
}
}
componentWillUnmount() {
clearInterval(this.timer);
}
render() {
return (
<>
<div>当前计数为:{this.state.count}</div>
</>
)
}
}
复制代码
效果图:
在函数式组件中使用生命周期函数:
函数式组件的useEffect
这一hook可以看成是上面三个生命周期的整合。useEffect
接收两个参数,第一个参数是个函数,第二个参数是个数组。回调函数会在组件刚挂载完毕时
调用一次(相当于componentDidMount
),该回调的返回值也是一个函数,这个返回的函数
会在组件销毁前
被调用(相当于componentWillUnmount
),但是effect 的清除阶段在每次重新渲染时都会执行,而不是只在卸载组件的时候执行一次,而第二个参数代表监听的对象列表,如果不传第二个参数,则默认监听所有变量的改变,即每一次变量改变都会执行第一个参数的函数体(相当于componentDidUpdate)。传入空数组则为不监听任何变量。useEffect
可以使用多次。
在函数式组件中
import React, { useState, useEffect } from 'react';
export default () => {
const [count, setCount] = useState(0);
let timer;
useEffect(() => {
if(timer) {
return;
}
if(count > 5) {
setCount(0);
}
timer = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => {
clearInterval(timer);
};
}, [count]);
return (
<>
<div>----RFC----</div>
<div>当前计数为:{count}</div>
</>
)
}
复制代码
效果图:
为什么使用React Hooks?
(1) 在组件之间复用状态逻辑很难 -> 使用
自定义Hook
实现复用状态,而不是使用render props
和高阶组件
等复杂且麻烦的方法。(2) 复杂组件变得难以理解 -> 不同的生命周期函数编写过于分散,
Hook
将组件中相互关联的部分拆分成更小的函数。(3) 难以理解的 class -> 需要时刻注意维护、绑定
this
,使得组件编写需要小心翼翼。
通过上面的代码对比,我们可以发现,使用函数式组件,利用hooks
可以让函数式组件完全拥有类组件的三大属性和生命周期函数,而且还免去了对this
的操作,用过vue的小伙伴应该对这个非常熟了,vue2到vue3的升级,对于编码过程的改变最为明显的应该就是不再使用this
,在用习惯了类组件后刚接触函数式组件时,感觉怎么写怎么别扭,但是用久了之后发现,真香。
写在最后 (^.^)
如果觉得我写的还不错的话,可以赏我个点赞哦^.^
如果有写错的地方、写的不好的地方也请大家指出,供我纠正。
我是CoCoyY1,一个记录自己学习的前端热爱者。
我的其他文章
Vue3中的expose函数 ———— 控制组件被ref时暴露的对象内容
vue3新语法糖——setup script ———— 使vue3的setup书写更简便,组件免注册、变量不用返回