目录
一、useState
二、useRef
三、useEffect
四、自定义Hook
五、Hooks使用规则
Hooks
原意是“挂钩”,指将类组件
中的部分功能直接可以挂钩
到函数组件
中,例如state、生命周期方法、副作用等功能。
为什么使用Hooks?
- 封装代码,提高复用性
- 更强的可读性
一、useState
概念
- useState是React的一个Hook函数,它运行我们向组件添加一个状态变量,从而控制影响组件的渲染结果
- 制作响应式数据
示例:useState 实现一个自增计数器
import {useState} from "react";
function App() {
// 1. 调用useState添加一个状态变量
// count:状态变量
// setCount:修改状态变量的方法
const [count, setCount] = useState(0);
// 2. 点击事件回调
const handleClick = () => {
/**
* 作用
* 1. 用传入的新值修改count
* 2. 重新使用新的count渲染UI
*/
setCount(count + 1);
}
return (
<div className="App">
<button onClick={handleClick}>{count}</button>
</div>
);
}
export default App;
规则
- 状态不可变:状态被认为是只读的,我们应该始终替换它而不是修改它,直接修改不能引发视图更新
- 个人理解:要修改状态变量,只能使用它提供的setXxx()方法,如果直接修改,该状态是不会联动视图一起修改的
- 修改状态对象:对于对象类型的状态变量,应该始终传给set方法一个全新的对象来进行修改
- 个人理解:如果状态变量是对象,那么传给set方法的应该是一个全新的对象,而不是在原本的对象的基础上修改,然后再传给set方法
二、useRef
作用
- 获取 / 操作DOM
步骤
- 使用useRef创建ref对象,并与JSX绑定
- 在DOM可用时,通过ref对象.current拿到DOM对象
- 渲染完毕之后(dom生成之后)才可用
import {useRef} from "react";
function App() {
// 1. 使用useRef创建ref对象,并与JSX绑定
const inputRef = useRef(null)
// 2. 在DOM可用时,通过ref对象.current拿到DOM对象
const showDOM = () => {
console.dir(inputRef.current)
}
return (
<div>
<input type="text" ref={inputRef}/>
<button onClick={() => showDOM()}>showDOM</button>
</div>
);
}
export default App;
三、useEffect
作用
- 用于在React组件中触发不是由事件引起而是由渲染本身引起的操作,比如发生AJAX请求、更改DOM等等
- 个人理解:类似Vue组件的生命周期,我们可以在不同生命周期内做不同的事情
基础使用
useEffect(() => {}, [])
参数详解
- 参数1:副作用函数,函数内部放置需要执行的操作
- 参数2(可选):在数组里放置依赖性,不同的依赖项会影响副作用函数的执行
-
- 空数组:副作用函数只会在组件渲染完毕后执行一次
import {useEffect, useState} from "react";
const URL = "http://geek.itheima.net/v1_0/channels"
function App() {
// 频道列表
const [list, setList] = useState([])
useEffect(() => {
async function getList() {
const res = await fetch(URL)
const channels = await res.json()
setList(channels.data.channels)
}
getList()
}, [])
return (
<div>
this is app
<ul>
{list.map(item => (
<li key={item.id}>{item.name}</li>
)
)}
</ul>
</div>
);
}
export default App;
依赖项参数说明(执行时机)
依赖项 | 副作用函数执行时机 |
无 |
|
空数组 | 只在初始渲染时执行一次 |
特定依赖项 |
|
import {useEffect, useState} from "react";
function App() {
const [count, setCount] = useState(0)
// 1. 没有依赖项:初始 + 组件更新
// useEffect(() => {
// console.log("副作用函数执行了")
// })
// 2. 空数组:初始执行一次
// useEffect(() => {
// console.log("副作用函数执行了")
// }, [])
// 3. 特定依赖项:初始 + 特定依赖性更新
useEffect(() => {
console.log("副作用函数执行了")
}, [count])
return (
<div>
this is app
<button onClick={() => setCount(count + 1)}>{count}</button>
</div>
);
}
export default App;
清除副作用
副作用操作
- 在useEffect中编写的由渲染本身引起的对接组件外部的操作
- 比如:useEffect中开启了一个定时器,我们想在组件卸载时把这个定时器清理掉,这个过程就是清理副作用
useEffect(() => {
// 实现副作用操作逻辑
return () => {
// 清除副作用逻辑
}
}, [])
说明:清除副作用的函数最常见的执行时机是在组件卸载时自动执行
四、自定义Hook
概念
- 自定义Hook是以use打头的函数,通过自定义Hook函数可以用来实现逻辑的封装和复用
示例:控制元素显示
import {useState} from "react";
// 封装自定义Hook
function useToggle() {
const [value, setValue] = useState(true);
const toggle = () => setValue(!value);
return {
value, toggle
}
}
function App() {
const {value, toggle} = useToggle();
return (
<div>
{value && <div>this is app</div>}
<button onClick={toggle}>toggle</button>
</div>
);
}
export default App;
五、Hooks使用规则
规则
1)只能在组件中或者其他自定义Hook函数中调用
2)只能在组件的顶层调用,不能嵌套在if、for、其他函数中
即函数的定义不能出现在上述情况中,但函数所产生的属性或方法可以
错误示例