React 的生命周期有哪些
Explain the React component lifecycle and its methods
一句话:三个阶段 ——挂载、更新、卸载。
- 挂载:
constructor→getDerivedStateFromProps→render→componentDidMount(DOM 已经有了,发请求、订阅、操作 DOM 都在这) - 更新:
getDerivedStateFromProps→shouldComponentUpdate(返回 false 就跳过渲染)→render→getSnapshotBeforeUpdate→componentDidUpdate(这里改 state 必须加条件, 否则死循环) - 卸载:
componentWillUnmount(清定时器、解绑监听、取消请求) - 出错:
getDerivedStateFromError+componentDidCatch(错误边界,见 #333)
三个被废弃的要知道:componentWillMount、componentWillReceiveProps、componentWillUpdate。原因是 Fiber 的 render 阶段可能被中断和重跑, 这几个方法可能被调用多次, 放在里面的副作用会重复执行。能说出这个原因很加分。
会追问:「请求为什么不放componentWillMount?」—— 除了上面的原因, 它在 SSR 时也会执行, 而且并不会更早拿到数据 (请求是异步的,反正要等)。
In one line: three phases — mounting, updating, unmounting.
- Mounting:
constructor→getDerivedStateFromProps→render→componentDidMount(the DOM exists now, so fetching, subscribing and DOM work all belong here) - Updating:
getDerivedStateFromProps→shouldComponentUpdate(return false to skip the render) →render→getSnapshotBeforeUpdate→componentDidUpdate(setting state here needs a condition, or you get an infinite loop) - Unmounting:
componentWillUnmount(clear timers, detach listeners, cancel requests) - On error:
getDerivedStateFromError+componentDidCatch(error boundaries, see #333)
Know the three that were deprecated: componentWillMount, componentWillReceiveProps, componentWillUpdate. The reason is that Fiber can interrupt and re-run the render phase, so these could fire more than once and any side effect inside them would run twice. Giving that reason earns real credit.
Follow-up: “Why not fetch in componentWillMount?” — besides the reason above, it also runs during SSR, and it does not get the data any sooner: the request is async, so you wait either way.