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) |
| 基于 props | useState(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更清晰。