为什么在setState之后调用getDerivedStateFromProps?

时间:2018-06-25 09:13:22

标签: reactjs getderivedstatefromprops

React引入了新的静态方法getDerivedStateFromProps(props, state),该方法在每个渲染方法之前都被调用,但是为什么呢?在更改道具后调用它对我来说很有意义,但是在setState之后却没有用,也许我错过了一些东西。

我正在根据我的公司要求创建一个datePicker组件,组件日期由道具控制。我在组件中具有以下状态。

selectedDate: number;
selectedMonth: number;
selectedYear: number;
currentMonth: number;
currentYear: number;
view: string;

selected表示从日期属性派生的所选日期,currentMonthcurrentYear代表当前日历视图中的月份和年份。

如果道具的date发生了selected*的变化,则currentMonthcurrentYear也应作相应的改变。为此,我使用的是getDerivedStateFromProps,但是假设用户单击“月份”名称,它将把日历视图切换到月份(而不是显示月份的日期名称),该函数为此更新了currentMonth使用setState,但该日期与应有的道具相同(包含上个月),但是将调用getDerivedStateFromProps,并且currentMonth仍与以前相同,而不是进行更改。

是的,我在state中创建了一个额外的变量来跟踪是否由于getDerivedStateFromProps而调用了setState,但我认为这不是正确的方法。

我做错了什么或缺少了什么,或者getDerivedStateFromProps不应在setState之后被调用。可能我做错了。

6 个答案:

答案 0 :(得分:1)

我也遇到了这个问题。所以我设置了另一个变量来检查道具是第一次收到的。

this.state={flag:true}

处于从道具获取状态

static getderivedstatefromprops(props, state){
   if(props.<*propName*> && flag){
      return({ props.<*propName*>, flag:false})
   }
}

如果要使用多个prop值,则需要相应地设置if语句(或任何其他逻辑)。

答案 1 :(得分:1)

我做了这样的事情

blit

答案 2 :(得分:0)

在这种情况下(根据道具更改来更新状态),请使用:

componentDidUpdate(prevProps) {
  // don't forget to compare props
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

componentDidUpdate将在每次更新后调用(由于道具更改/状态更改)。因此您应该检查道具是否已更改(通过this.props.userID !== prevProps.userID)。

答案 3 :(得分:0)

下面的内容对我来说似乎很有效,而且很一般。

在构造函数中:

this.state = {
    props,
    // other stuff
}

在 gDSFP 中:

static getDerivedStateFromProps(newProps, state) {
    if (state.props !== newProps)
        // Compute and return new state relevant to property change
    else
        return state;
}

一些实验证实“状态”不再自动是旧状态,但在这个钩子实例中是新设置的状态与现有道具的结合。我想添加钩子是为了不必直接调用 gDSFP 来重复依赖于道具的复杂状态演变,例如

this.setState(ClassName.getDerivedStateFromProps(this.props, newState))

问题在于,这并不是一个重大的变化,但如果旧代码在 getDerivedStateFromProps 中不必要地进行大量计算,则可能会导致微妙的低效率。例如,我刚刚发现一个复杂的对象被三次构造,一次是真实的,另外两次只是因为这个新钩子。

答案 4 :(得分:-1)

问题本身就有答案。 “在每个渲染方法之前调用”。每当您执行setState时,就会调用render方法。

我建议您将状态变量currentMonthcurrentYear提升到父组件,并将它们作为prop与其他三个一起传递。您还可以将变更处理程序作为prop传递,并从子级进行调用。

在初始render上- 可以将currentMonthcurrentYear设置为null,这样您就可以显示默认内容的逻辑。当有人以月份名称作为小鸡时,您可以从父母那里呼叫changeHandler,这会传递新的道具。现在在getderivedstatefromprops中,您不再将currentMonthcurrentYear设置为“ null”,因此您知道月份已更改。

答案 5 :(得分:-1)

只要收到新道具 setState forceUpdate getDerivedStateFromProps钩子就会起作用。

16.3版本中,无论何时使用getDerivedStateFromProps,React都不会影响setState。但是他们从16.4开始的版本中对其进行了改进,因此无论何时调用setState都被钩住getDerivedStateFromProps

这里是从React lifecycle diagram中提取的图像:

16.3

enter image description here

^ 16.4

enter image description here


因此,由您决定何时通过正确检查道具和状态来钩住getDerivedStateFromProps。这是一个示例:

static getDerivedStateFromProps (props, state) {
  // check your condition when it should run?
  if(props.currentMonth != state.currentMonth) {
    return {
      currentMonth: state.currentMonth
    }
  }
  // otherwise, don't do anything
  else {
   return null
  }
}