为什么在setState之后调用getDerivedStateFromProps?

问题描述 投票:19回答:3

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

我根据我公司的要求创建了一个datePicker组件,在组件日期由prop支持。我在组件中有以下状态。

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

selected表示从date prop和currentMonth派生的选定日期,currentYear表示当前日历视图中的月份和年份。

如果来自道具的date改变selected*,则应相应更改currentMonthcurrentYear。为此,我使用getDerivedStateFromProps但是让用户点击月份名称将日历视图切换到月份(而不是显示月份的日期名称),该函数使用setState更新currentMonth,但是日期是道具是与之前(包含前一个月)相同,但应调用getDerivedStateFromProps,而currentMonth再次与之前相同而不是更改。

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

无论是我做错了什么或丢失的东西或getDerivedStateFromProps不应该在setState后调用。可能我做错了什么。

reactjs getderivedstatefromprops
3个回答
2
投票

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

this.state={flag:true}

在getderivedstatefromprops

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

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


2
投票

每当收到新的props,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
  }
}

1
投票

我做了这样的事

constructor(props) {
    super(props);
    this.state = {
        expanded: props.expanded,
        ownUpdate: false
    }
}

static getDerivedStateFromProps(props, state) {
    if (state.ownUpdate) {
        return {
            expanded: state.expanded,
            ownUpdate: false
        };
    } else if (props.expanded !== state.expanded) {
        return {
            expanded: props.expanded
        };
    }
    return null;
}

toggle() {
    this.props.onAftePress(this.state.expanded, this.props.index);
    this.setState({
        expanded: !this.state.expanded,
        ownUpdate: true
    })
}

0
投票

你的问题本身就有答案。 “在每个渲染方法之前调用它”。每当你做一个setState时,将调用render方法。

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

在最初的render - currentMonthcurrentYear可以设置为null,这样你就可以拥有显示默认内容的逻辑。当有人按月名称时,你可以从父母那里调用changeHandler,这将传递新的道具。现在在getderivedstatefromprops你不再有currentMonthcurrentYear为'null所以你知道这个月已经改变了。

© www.soinside.com 2019 - 2024. All rights reserved.