React Hooks
useState(函数式编程)
// 使用useState来创建状态
// 1. 引入
import React, { useState } from 'react'
function StateFun () {
// 2. 接收一个参数做为初始值
const [name, setName] = useState('111')
// 3. 返回一个数组 第一个值为状态 第二个为改变状态的值
return <div onClick={() => { setName('222') }}>函数组件{name}</div>
// setName修改值时它是同步还是异步?
// setName 是异步更新
// 连续调用 setName 会发生什么?
// 传入的是一个普通值,他只会进行最后一次更新
// 传入一个函数的话,它会进行两次赋值,因为它更新的值是基于之前的值来执行,所以在开发中推荐使用函数传入的形式进行修改;
}
export default StateFun
useEffect(解决副作用)
执行时机在 rendar之后
// 1. 引入
import React, { useEffect, useState } from 'react'
function StateFun () {
const [num, setNum] = useState(1)
// 2. 接收一个函数作为参数
// 3. 接收第二个参数 依赖列表 依赖更新时,才执行参数 空数组执行一次 无第二个参数时 全都执行
// 4. 先执行返回函数 再执行参数函数
useEffect(() => {
console.log('2') // 参数函数
return () => {
console.log('1') // 返回函数
}
})
return <div onClick={() => { setNum(num => num + 1) }}>函数组件{num}</div>
}
export default StateFun
useLayoutEffect(监测DOM)
执行时机在 DOM更新之后
// 1. 引入
import React, { useEffect, useState } from 'react'
function StateFun () {
const [num, setNum] = useState(1)
// 2. 接收一个函数作为参数
// 3. 接收第二个参数 依赖列表 依赖更新时,才执行参数 空数组执行一次 无第二个参数时 全都执行
// 4. 先执行返回函数 再执行参数函数
useLayoutEffect(() => {
console.log('2') // 参数函数
return () => {
console.log('1') // 返回函数
}
})
return <div onClick={() => { setNum(num => num + 1) }}>函数组件{num}</div>
}
export default StateFun
useMemo(组件跟随状态更新)
// 1. 引入
import React, { useState, useMemo } from 'react'
function StateFun () {
const [age, setAge] = useState(10)
const [name, setName] = useState(1)
// 2. 接收一个函数作为参数
// 3. 接收第二个参数 依赖列表 依赖更新时,才执行参数 空数组执行一次 无第二个参数时 全都执行
// 4. 返回的是一个值
const ageDouble = useMemo(() => {
return age * 2
}, [age])
return <div onClick={() => { setName(name => name + 1) }}>age:{age} name:{name} 双倍:{ageDouble}</div>
}
export default StateFun
useCallback(组件跟随状态更新)
// 1. 引入
import React, { useState, useCallback } from 'react'
function StateFun () {
const [age, setAge] = useState(10)
const [name, setName] = useState(1)
// 2. useMemo useCallback 使用相同
// 3. useMemo返回的是一个值 useCallback返回一个函数
// 4. 不同点 useMemo缓存的是一个值 useCallback缓存一个函数
const ageDouble = useCallback(() => {
return age * 2
}, [age])
return <div onClick={() => { setAge(name => name + 1) }}>age:{age} name:{name} 双倍:{ageDouble()}</div>
}
export default StateFun
useRef(长久保存数据)
// 1. 引入
import React, { useState, useEffect, useRef } from 'react'
function StateFun () {
const [num, setNum] = useState(1)
const ref = useRef()
// 返回的 ref 对象在组件的整个生命周期内保持不变 useRef 类似于类组件的 this
// 修改 Ref 对象中current的值并不会引发组件的重新渲染
useEffect(() => {
ref.current = setInterval(() => {
setNum(num => num + 1)
}, 400)
return () => {
clearInterval(ref.current)
}
}, [])
useEffect(() => {
if (num > 10) {
clearInterval(ref.current)
}
}, [num])
return <div> num:{num}</div>
}
export default StateFun
useContext(组件之间共享状态)
import React, { useContext, createContext, useState } from 'react'
// 引入 useContext createContext
// 通过 createContext创建一个Context句柄
// Context.Provider来确定共享范围
// 通过value 分发内容
// 子组件通过useContext(Context句柄) 来获取数据
const Context = createContext()
function StateFun () {
const [num, setNum] = useState(1)
console.log('Context', Context)
return <div>
父组件:{num}
<Context.Provider value={num}>
<Item1></Item1>
<Item2></Item2>
</Context.Provider>
</div>
}
function Item1 () {
const num = useContext(Context)
return <div>子组件1 num:{num}</div>
}
function Item2 () {
const num = useContext(Context)
return <div>子组件2 num:{num}</div>
}
export default StateFun
useReducer(复杂逻辑简单化)
import React, { useReducer } from 'react'
const store = {
num: 10
}
// useReducer使用方法
// 创建 数据仓库(store) 和 管理者(reducer)
// 通过 useReducer(reducer, store)来获取state和dispatch
const reducer = (state, action) => {
console.log('state', state)
console.log('action', action)
switch (action.type) {
case 'setNum':
return {
...state,
num: action.num
}
default:
return {
...state
}
}
}
function StateFun () {
const [state, dispatch] = useReducer(reducer, store)
return <div onClick={() => {
dispatch({
type: 'setNum',
num: 100
})
}}>
父组件:{state.num}
</div>
}
export default StateFun