React函数组件配合Hooks是当前前端开发的标准写法,但useState、useEffect、useMemo用错,轻则重复渲染,重则请求混乱、页面卡顿。本文围绕React的状态管理、副作用处理与性能优化,整理可直接抄的写法与常见坑,适合Vue3/React切换期的前端工程师。
React Hooks与函数组件基础
React 19中Hooks是函数组件的唯一推荐方式。组件内每个render执行一遍函数体,Hooks按调用顺序注册状态,所以Hooks不能写在if/循环里。理解这个模型,后面很多问题都能解释。
useState与useReducer:状态更新与不可变
const [count, setCount] = useState(0)
// 批量更新用函数式
setCount(c => c + 1)
state更新要求不可变:对象、数组要复制新引用,否则组件不重渲染。状态逻辑复杂(多个子状态联动、校验、undo)就换useReducer,把状态机集中到reducer里,测试也方便。
useEffect副作用:请求、订阅与竞态处理
useEffect(() => {
let ignore = false
async function load() {
const data = await fetch(`/api/item?id=${id}`).then(r => r.json())
if (!ignore) setData(data)
}
load()
return () => { ignore = true }
}, [id])
这个ignore模式解决大多数竞态:组件卸载或参数变化后,旧请求结果不再覆盖新状态。依赖数组不能缺依赖,否则闭包捕获旧值;不能无脑省略,否则陷入反复执行。
减少渲染:memo、useMemo与useCallback
组件默认父级重渲染,子组件跟随重渲染。优化三板斧:
React.memo包装子组件,props不变则跳过。
useMemo缓存复杂计算的结果,依赖不变直接复用。
useCallback缓存函数引用,配合memo防止子组件被”新函数”触发重渲染。
const ItemList = memo(function ItemList({ items, onPick }) {
return items.map(it => <Item key={it.id} {...it} onClick={onPick} />)
})
// 父组件里
const handlePick = useCallback((id) => setCur(id), [])
记住一个原则:性能优化先看实际渲染耗时,别为所有组件套memo,过度优化增加心智负担。
并发特性:startTransition与useDeferredValue
React 18引入并发渲染。state更新导致卡顿,把低优先级更新包进startTransition,UI保持响应:
const [query, setQuery] = useState('')
const [isPending, startTransition] = useTransition()
startTransition(() => setFiltered(filterList(query)))
列表筛选、搜索联想这类高频大计算场景优先用startTransition,比手动debounce更贴近框架设计。
服务端渲染与Next.js
大型应用普遍上服务端渲染(SSR)。Next.js的App Router把布局、加载态、流式渲染做成声明式,RSC(React Server Component)让大部分组件在服务器执行,减少客户端包体。注意SSR下不要用window/document;客户端专属逻辑用”use client”或动态导入。
性能问题定位:Profiler与构建分析
用React DevTools Profiler记录交互,看火焰图中的渲染时长和组件耗时。构建产物分析用bundle analyzer:
npx next build --debug
npx source-map-explorer .next/static/chunks/*.js
定位到具体组件后,用Suspense做代码分割、懒加载图片,把首屏JS压下来。前端性能优化始终围绕两条线:少渲染、少加载。Hooks用对只是起点,配合构建分析和运行时分析才能把优化做到位。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/react-kuang-jia-shi-zhan-hooks-zhuang-tai-guan-li-yu-qian/