Lin Du
Lin Du

Reputation: 102327

setState conflicts with getDerivedStateFromProps

import React, { Component } from "react";

export interface MyComponentProps {
  show: boolean;
}
export interface MyComponentState {
  show: boolean;
}

export default class App extends Component<MyComponentProps, MyComponentState> {
  static defaultProps = {
    show: true
  };
  static getDerivedStateFromProps(props: MyComponentProps) {
    console.log("getDerivedStateFromProps: ", props);
    if ("show" in props) {
      return { show: props.show };
    }
    return null;
  }
  constructor(props: MyComponentProps) {
    super(props);
    this.state = {
      show: props.show
    };
  }
  onClick() {
    this.setState({ show: false });
  }
  render() {
    const { show } = this.state;
    return (
      <div>
        {show ? "teresa teng" : ""}
        <button type="button" onClick={() => this.onClick()}>
          toggle
        </button>
      </div>
    );
  }
}

getDerivedStateFromProps() static method will be executed after setState(). So I click the button to try to change the value of state.show to false, but the getDerivedStateFromProps() method will change state.show to true. So the text will always be visible.

getDerivedStateFromProps intends to use the props passed in by the parent component to update the state.

How can I solve this? Playground codesandbox.

Upvotes: 0

Views: 39

Answers (1)

Rohan Agarwal
Rohan Agarwal

Reputation: 2609

getDerviedStateFromProps is bound to run after every prop and state change. This was not an actual design but this change in functionality was introduced in React version 16.4 (if I remember correctly).

Now, if you want to update the local show i.e. your state on the basis of your props, you can:

  1. Pass a callback which updates show for you in the parent component and then use the new prop value.(As mentioned by @jonrsharpe in the comments).

  2. You can also make use of a key prop which tells your component to completely unmount and mount itself in case of a key change. This will lead to the state getting reset based on the value of the props.

For ex,

<App show={this.state.show} 
key={this.state.show}/>

Example CodeSandBox

Upvotes: 1

Related Questions