Skip to content

getDerivedStateFromProps

就是为了让 props 能更新到组件内部 state 中来。

作用:

  1. 当组件 props 发生变化时,更新内部的 state

时机

在 beginWork 阶段 遇到节点为 ClassComponent 时,会调用 getDerivedStateFromProps 方法。

源码

js
/**
 * 回调 Class 组件的 getDerivedStateFromProps 方法
 * 并返回新的state
 *
 * @param {*} workInProgress
 * @param {*} ctor
 * @param {*} getDerivedStateFromProps
 * @param {*} nextProps
 */
function applyDerivedStateFromProps(
  workInProgress: Fiber,
  ctor: any,
  getDerivedStateFromProps: (props: any, state: any) => any,
  nextProps: any
) {
  const prevState = workInProgress.memoizedState;
  // 回调 getDerivedStateFromProps 来获取新的state
  let partialState = getDerivedStateFromProps(nextProps, prevState);
  if (__DEV__) {
    if (
      debugRenderPhaseSideEffectsForStrictMode &&
      workInProgress.mode & StrictLegacyMode
    ) {
      setIsStrictModeForDevtools(true);
      try {
        // Invoke the function an extra time to help detect side-effects.
        partialState = getDerivedStateFromProps(nextProps, prevState);
      } finally {
        setIsStrictModeForDevtools(false);
      }
    }
    warnOnUndefinedDerivedState(ctor, partialState);
  }
  // Merge the partial state and the previous state.
  // 如果没有返回值,则直接返回prevState
  // 否则返回一个新的state对象
  const memoizedState =
    partialState === null || partialState === undefined
      ? prevState
      : assign({}, prevState, partialState);
  // 将新的 state 赋值给 workInProgress.memoizedState
  workInProgress.memoizedState = memoizedState;

  // Once the update queue is empty, persist the derived state onto the
  // base state.
  // 将新的 state 赋值给 workInProgress.updateQueue.baseState
  if (workInProgress.lanes === NoLanes) {
    // Queue is always non-null for classes
    const updateQueue: UpdateQueue<any> = (workInProgress.updateQueue: any);
    updateQueue.baseState = memoizedState;
  }
}

这个函数会根据 nextProps, prevState 来调用 Class 组件的 getDerivedStateFromProps 方法,获取新的 state。

且对于新的 state 判断是否为 null 或者 undefined,如果是则直接返回 prevState,否则返回一个新的 state 对象(浅合并)。

结论:

  1. 因为这个生命周期是静态方法,同时要保持它是纯函数,不要产生副作用。
  2. 在使用此生命周期时,要注意把传入的 prop 值和之前传入的 prop 进行比较(这个 prop 值最好有唯一性,或者使用一个唯一性的 prop 值来专门比较)。
  3. 不使用 getDerivedStateFromProps,可以改成组件保持完全不可控模式,通过初始值和 key 值来实现 prop 改变 state 的情景。