FumadocsZDecode
React

状态初始化

getInitialState 是 React createClass 时代的 API,已在 ES6 类组件中被 constructor 替代,在函数组件中进一步被 useState 取代。现在你不需要它,但了解它的演变有助于理解 React 状态管理的设计思路。

// ❌ 已废弃 —— React.createClass 时代
const C = React.createClass({
  getInitialState() {
    return { count: 0 }
  },
})

// ✅ ES6 类组件
class C extends React.Component {
  constructor(props) {
    super(props)
    this.state = { count: 0 }
  }
}

// ✅ 函数组件(现代首选)
function C() {
  const [count, setCount] = useState(0)
}

一、演变历程

React 状态初始化经历了三个阶段:

阶段方式特点
React.createClass(弃)getInitialState自动绑定 this,mixins 复用逻辑
ES6 类组件constructor手动绑定 this,class 继承
函数组件(现代)useState无 this 问题,自定义 Hook 复用逻辑

二、不同数据来源的初始化方式

根据初始值的数据来源选择合适的写法:

数据来源写法
固定初始值useState(0)
基于 propsuseState(props.initialValue)
复杂计算useState(() => expensiveComputation(props)) — 惰性初始化,仅执行一次

三、性能优化

惰性初始化

当初始值需要复杂计算时,传函数而非直接传值。函数只在组件首次渲染时执行一次,后续重渲染不会重复计算:

// ❌ 每次渲染都执行 expensiveComputation(虽然只用第一次结果)
const [state, setState] = useState(expensiveComputation())

// ✅ 惰性初始化 —— 仅首次渲染执行
const [state, setState] = useState(() => expensiveComputation())

避免组件内重复创建

如果初始值是引用类型且不依赖 props,提到组件外部,避免每次渲染都创建新对象:

// ❌ 每次渲染创建新对象
function Component() {
  const [state, setState] = useState({ data: createExpensiveObject() })
}

// ✅ 提到外部,只创建一次
const defaultData = createExpensiveObject()
function Component() {
  const [state, setState] = useState({ data: defaultData })
}

四、注意事项

使用 useState 时有几个容易踩的坑:

  • 不要在条件语句中调用 useState——Hook 的调用顺序必须稳定,条件判断会破坏 React 的内部状态映射。
  • 保持初始值类型一致——初始 state 的类型和后续更新的类型应对齐,避免类型突变导致的隐藏 bug。
  • 复杂状态用 useReducer——当 state 逻辑涉及多个子值或状态转换复杂时,useReducer 比多个 useState 更清晰。

On this page