Files
2026-07-13 21:36:17 +08:00

2.0 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Use Lazy State Initialization MEDIUM 每次渲染时浪费的计算 react, hooks, useState, performance, initialization

使用惰性状态初始化

对于昂贵的初始值,向 useState 传入一个函数。不使用函数形式时,初始化器会在每次渲染时运行,尽管该值只使用一次。

错误做法(每次渲染都运行):

function FilteredList({ items }: { items: Item[] }) {
  // buildSearchIndex() 在每次渲染时都运行,即使是在初始化之后
  const [searchIndex, setSearchIndex] = useState(buildSearchIndex(items))
  const [query, setQuery] = useState('')
  
  // 当 query 变化时,buildSearchIndex 会再次不必要地运行
  return <SearchResults index={searchIndex} query={query} />
}

function UserProfile() {
  // JSON.parse 在每次渲染时运行
  const [settings, setSettings] = useState(
    JSON.parse(localStorage.getItem('settings') || '{}')
  )
  
  return <SettingsForm settings={settings} onChange={setSettings} />
}

正确做法(仅运行一次):

function FilteredList({ items }: { items: Item[] }) {
  // buildSearchIndex() 仅在初始渲染时运行
  const [searchIndex, setSearchIndex] = useState(() => buildSearchIndex(items))
  const [query, setQuery] = useState('')
  
  return <SearchResults index={searchIndex} query={query} />
}

function UserProfile() {
  // JSON.parse 仅在初始渲染时运行
  const [settings, setSettings] = useState(() => {
    const stored = localStorage.getItem('settings')
    return stored ? JSON.parse(stored) : {}
  })
  
  return <SettingsForm settings={settings} onChange={setSettings} />
}

当从 localStorage/sessionStorage 计算初始值、构建数据结构(索引、映射)、从 DOM 读取或执行繁重的转换时,请使用惰性初始化。

对于简单的基本类型(useState(0))、直接引用(useState(props.value))或廉价的字面量(useState({})),则不需要函数形式。