const Component = () => {
useEffect(() => {}, [])
return <div>Demo</div>
};
// 是否想过,这两种调用方式有什么区别?
Component() // 这样写会怎样?
<Component /> // 这样写会怎样?
先说答案:第一种写法可能会让你的应用崩溃!
直接调用组件函数(如
Component())是一个危险动作,它会绕开React的调度机制,导致上下文状态错乱,可能让你的应用崩溃!!
下面来挖掘一下这个容易被忽视但很危险的问题。
通过一个实验直观感受问题所在:
function App() {
const [count, setCount] = useState(0)
return (
<>
<button onClick={() => setCount(count + 1)}>点击: {count}</button>
{count % 2 === 0 ? A() : B()}
{count === 2 && A()}
</>
)
}
function A() {
const [value, setValue] = useState('A')
return <div>组件A: {value}</div>
}
function B() {
const [value, setValue] = useState('B')
return <div>组件B: {value}</div>
}
现象结果:
count=0):显示组件A,状态正常count=1):显示组件B,但界面上显示的值是 “组件B: A”count=2):直接报错:Rendered more hooks than during the previous render普通函数调用没有状态持久性:
function simpleFunction() {
let count = 0
count++
return count
}
simpleFunction() // 返回 1
simpleFunction() // 还是返回 1,每次都是全新作用域
React 的解决方案:Fiber 架构与 Hooks 链表
React 通过 Fiber 架构为每个组件建立独立的状态存储:
React 需要在函数组件外部存储状态。为了管理组件树和状态,React 内部使用了一种叫做 Fiber 的数据结构
// 每个组件都对应一个 Fiber 节点
const fiber = {
type: Component, // 组件类型
memoizedState: null, // Hooks 链存储在这里
// ... 其他属性
}