hooks
什么是 hooks
Hooks
: 直意钩子,可以让函数组件里“钩入”
React 的状态 state
及生命周期等特性的函数。
hooks 的作用
- 为函数组件提供状态、生命周期
- 组件的状态逻辑复用
- 解决 class 组件自身的问题
- Hooks 只能在函数组件中使用
class 组件自身的问题
根据状态来渲染UI时 class
组件不能发挥它最重要的功能
- 组件之间很少继承
- 组件之间很少通讯
- 通用逻辑不好复用
hooks 配合函数式组件的好处
- 函数本身比较简单,更适合根据状态来渲染UI
- hooks 让函数组件内部有了操作维护状态的能力
- hooks 带来了组件的逻辑复用能力
hooks 的常用 API
1 . useState
作用 : useState
可以为函数组件提供状态
useState
的使用:
- 导入
useState
函数 ,import React {useState} from 'react'
- 调用
useState()
方法 ,const [count,steCount] = useState(数据初始值)
useState
的参数 : 状态初始值。
- 参数的两种格式
- 格式1:传入值
useState(0) 或 useState('abc')
- 格式2:传入回调
useState(() => { return 初始值 })
, 回调函数的返回值就是状态的当前值
- 格式1:传入值
- 注意:初始值可以是任意值(例: 数值、字符串等),而 class 组件中的 state 必须是对象
useState
的返回值 : 是一个数组 [count,steCount]
count
: 状态,就是数据名stecount
:修改状态的函数, 可以修改count
的数据 ( 响应式 )- 注意: 修改状态的函数名称以 set 开头,后面跟上状态的名称
setXXX
的参数有两个格式setCount(100)
- 函数式
setCount(count(上一次的值) => { 操作数据业务代码 return count(新值) })
可以用来对count
进行叠加
import React, { useState } from 'react'
import ReactDom from 'react-dom'
export default function App () {
const [count, setCount] = useState('')
return (
<div>
{/* 展示状态值 */}
<h1>useState Hook -> {content}</h1>
{/* 点击按钮,让状态值 +1 */}
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
)
}
ReactDom.render(<App />, document.getElementById('root'))
useState-处理表单元素
使用 :
- 导入
useState
函数 - 调用 useState() 方法 ,
const [count,steCount] = useState(数据)
- render函数中使用 :
<input value={content} onChange={(e) => setContent(e.target.value)} />
useState 的注意点
- useState 的初始值(参数)只会在组件第一次渲染时生效
- 为函数组件提供多个状态 ,
useState(状态1) useState(状态2)
,每调用一次 useState Hook 可以提供一个状态。 - useState 只能直接出现在函数组件内部
- useState 不能嵌套在
if
或者for
语句中
2 . useEffect
useEffect
副作用 : 对于react组件来说,除了渲染UI之外的其他操作,都可以称之为副作用
函数式组件的作用划分:
- 主作用 : 就是根据数据(state/props)渲染 UI
- 副作用 : 数据(Ajax)请求、手动修改 DOM、开启定时器,清空定时器,添加事件监听,删除事件, localStorage 操作等
useEffect-基本使用
- 导入
useEffect
import { useEffect } from 'react'
- 使用
useEffect(() => {
// 副作用函数的操作
}, [依赖项,依赖项2...])
useEffect
两个参数
- 参数1 : 回调函数, 操作副作用函数。
- 参数2 : 数组, 执行副作用函数的依赖项, 决定了什么时机执行参数1(副作用函数)
useEffect
四种执行时机
情况1 : 不写第二个参数。
- 执行时机 :render 函数执行执行之后, 每次状态改变都会执行
- 相当于 React 中的
componentDidmount
组件挂载后 +componentDidUpdate
组件更新后
情况2 : 第二个参数是空数组。
- 执行时机 :初次 render 函数执行执行之后执行, 只执行一次,后续修改 DOM 不执行
- 相当于 React 中的
componentDidMount
组件挂载后 - 使用场景 :1.事件绑定, 2.发送请求获取数据等。
情况3 : 带第二个参数(数组格式),并指定了依赖项。
- 执行时机:(1)初始执行一次 (2)依赖项的值变化了就会执行
- 相当于 Watcher 对依赖项进行监听
情况4 : useEffect 副作用函数的返回值,清理副作用
useEffect(() => {
// 副作用函数的内容
return ()=>{ /* 做清理工作*/ } // 清理函数
}, [])
- 清理函数的执行时机:
- 清理函数会在组件卸载时以及下一次副作用函数调用之前执行
- 相当于 React 中的
componentWillUnmount
组件卸载
3 . useRef
使用场景 : 在 React 中进行 DOM 操作时,用 useRef 来获取 DOM
作用 :
- 使用用
useRef()
后 得到一个带有 current 属性的对象 , 可以用其操作 DOM
useRef 基本使用
- 导入 useRef
import React, { useRef } from 'react'
- 调用useRef(初值),得到引用对象
const 包含current的对象名 = useRef(null)
- 把引用对象设置
ref
给任意的组件/元素
<input ref={包含current的对象名} />
- 通过引用对象
.current
获取组件/元素
对象名.current.value
获取 input 的值
注意 :
- 参数:在获取 DOM 时,一般都设置为 null
- 调用
useRef
返回值:包含current
属性的对象。 - 只要在
React
中进行 DOM 操作,都可以通过useRef Hook
来获取 DOM(例 : 获取 DOM 的宽高等)。 useRef
不仅仅可以用于操作 DOM,还可以操作组件
useRef 封装可共享数据
- 导入 useRef
import React, { useRef } from 'react'
- 调用useRef
- 组件中使用
const timeRef = useRef(null)
- 组件中使用
- 向引用的current中存入数据
timeRef.current = 需要在多次渲染之间共享的数据
4 . useContext
实现全局状态共享
useContext 使用步骤
-
导入并调用
createContext
方法,得到Context
对象import { createContext } from 'react' export const Context = createContext()
-
使用 Provider 组件包裹根组件,并通过 value 属性提供要共享的数据
return ( <Context.Provider value={ 这里放要传递的数据 }> <根组件的内容/> </Provider> )
-
在后代组件中,导入
useContext
和context
- 调用 useContext(context) 得到 value 的值
- context : 是第一步中导出的
import React, { useContext } from 'react' import { Context } from './index' const 函数组件 = () => { const 公共数据 = useContext(Context) return ( 函数组件的内容 ) }
自定义 hooks
自定义 hooks 的作用
除了使用内置的 Hooks 之外,还可以创建自定义 Hooks。自定义 Hooks 针对不同组件实现不同状态 逻辑复用。
自定义 hooks 特点 :
- 自定义 Hooks 是一个函数
- 约定函数名称必须以 use 开头,React 就是通过函数名称是否以 use 开头来判断是不是 Hooks
- Hooks 只能在函数组件中或其他自定义 Hooks 中使用,否则,会报错!
- 自定义 Hooks 是用来实现组件的状态逻辑复用的,使用和普通封装函数一样
使用场景
复用的逻辑代码 , 提取到 Hooks 中单独封装, 使用时直接导入调用