react 基础API
2025年7月3日 15:03
1. useEffect
- 浏览器重新绘制之后触发
- 参数(setup,dependencies?)
- 异步执行
- 挂载组件时执行setup,依赖更新时先执行cleanup,再执行setup
2. useLayoutEffect
- 浏览器重新绘制之前触发
- 参数(setup,dependencies?)
- 同步执行,会阻塞DOM渲染
- 挂载组件时执行setup,依赖更新时先执行cleanup,再执行setup
3. useReducer
const [state, dispatch] = useReducer(reducerFn, initiaValue, inituaValueFn?)
reducerFn:处理函数,参数:state, action,返回值:新的state
initiaValue:state默认值
inituaValueFn:默认值函数,用于初始化state,优先执行,非必填
const reducerfn = (state, action) => {
if (action==='inc') {
return state++
}
if (action==='dec') {
return state--
}
}
const [state, dispatch] = useReducer(reducerfn, -1, ()=> {
// 高于默认值的优先级
return 0
})
<Button onClick={() => dispatch('inc')}>增加</Button>
<Button onClick={() => dispatch('dec')}>减少</Button>
4. useSyncExternalStore
useSyncExternalStore
用于从外部存储(例如状态管理库、浏览器 API等)获取状态并在组件中同步显示。跟踪外部状态。
useSyncExternalStore
使用场景:
- 订阅外部 store 例如(redux,mobx,Zustand,jotai)
- 订阅浏览器AP| 例如(online,storage,location, history hash)等
抽离逻辑,编写自定义hooks
const res = useSyncExternalStore(subscribe, getSnapshot, getSeeverSnapShot?)
sybscribe:订阅数据源的变化,接受一个回调函数在数据源更新时调用此函数
getSnapShot:获取当前数据源的快照(当前信息)
getSeeverSnapShot:服务端使用
// hooks/useStorage.tsx
import { useSyncExternalStore } from 'react'
export const useStorage = (key: string, initiaValue: number) => {
const subscribe = (callback: () => void) => {
window.addEventListener('storage', callback)
return () => {
window.removeEventListener('storage', callback)
}
}
const getSnapShot = () => {
return localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key)!) : initiaValue
}
const data = useSyncExternalStore(subscribe, getSnapShot)
const setData = (value: any) => {
localStorage.setItem(key, JSON.stringify(value))
// 手动触发eventStorage事件,通知订阅
window.dispatchEvent(new Event('storage'))
}
return [data, setData]
}
// views/page.tsx
import { useStorage } from "./hooks/useStorage";
function App() {
const [token, setToken] = useStorage('token', 0)
return (
<>
<h1>hooks useStorage</h1>
<div>
<p> token is {token} </p>
<button onClick={() => setToken(token + 1)}> token ++ </button>
<button onClick={() => setToken(token - 1)}> token -- </button>
</div>
</>
)
}
export default App
5. useTransition
useTransition
用于优化用户界面响应性的 Hook,它允许你在不阻塞用户交互的前提下,优雅地处理状态更新带来的加载状态(如“挂起”或“过渡”) 。
useTransition
作用:
- 状态更新通常是同步的,调用
setState
会立即重新渲染组件树,可能会导致页面卡顿,特别是在处理复杂计算或大量数据更新时。useTransition
将某些状态更新标记为“非紧急”(过渡态),从而优先处理更紧急的 UI 更新(比如输入框的响应) 。
useTransition
使用场景:
- 数据加载时的“pending”状态展示
- 页面切换时的平滑过渡
- 大型表单提交等场景
6. useDeferredValue
useDeferredValue
用于优化用户界面响应性的 Hook,它允许你在不阻塞渲染的前提下,延迟更新某些非紧急的状态值,从而保持 UI 的流畅性。
useDeferredValue
作用:
- 延迟使用新的值进行渲染,优先显示旧值,直到浏览器空闲时再更新为新值。
useDeferredValue
使用场景:
- 搜索输入框的自动补全
- 列表滚动时的平滑更新
- 大量数据展示时的渐进式渲染
7. useDeferred 对比 useTransition
特性 | useDeferredValue | useTransition |
---|---|---|
控制对象 | 值(value) | 状态更新(state update) |
是否需要包装副作用 | 否 | 是 |
是否有 isPending 状态 |
否 | 是 |
适用场景 | 延迟更新某个值(如列表、文本) | 控制状态更新优先级,显示 loading 状态 |
8. useImperativeHandle & forwardRef
用于自定义暴露子组件方法或属性给父组件调用的 Hook,它通常与 forwardRef
一起使用。
import { useImperativeHandle, forwardRef, useRef } from "react";
// 子组件,必须配合 forwardRef
const Child_ = forwardRef((props, ref)=>{
const Child_reff = useRef(null)
const focusInput = () => {
Child_reff.current!.focus()
}
const selectInput = () => {
Child_reff.current!.select()
}
const BlurInput = () => {
Child_reff.current!.blur()
}
// 暴露方法给父组件
useImperativeHandle(ref,() => ({
focus: focusInput,
select: selectInput,
blur: BlurInput,
}))
return <input ref={Child_reff} type="text" />
})
// 父组件
function Parent_() {
const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current!.focus(); // 调用子组件方法
};
const handleSelect = () => {
inputRef.current!.select(); // 调用子组件方法
};
const handleBlur = () => {
inputRef.current!.blur(); // 调用子组件方法
};
return (
<>
<div>
<h1>hooks useImperativeHandle forwardRef</h1>
<p> useImperativeHandle </p>
<br />
<Child_ ref={inputRef} />
<button onClick={handleFocus}>输入框聚焦</button>
<button onClick={handleSelect}>选中输入框文本</button>
<button onClick={handleBlur}>输入框失焦</button>
</div>
</>
)
}
export default Parent_