Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can't find variable error in `getDerivedStateFromProps`

I am updating some deprecated code in a react native app, and so I replaced this:

  UNSAFE_componentWillReceiveProps(nextProps) {
    if(
      this.props.started != nextProps.started ||
      this.props.stopped != nextProps.stopped ||
      this.props.durationOverride != nextProps.durationOverride ||
      this.props.editable != nextProps.editable
    ) {
      this.loadTimer(nextProps);
    }
  }

… with this:

  static async getDerivedStateFromProps(nextProps, props) {
    if(
      props.started != nextProps.started ||
      props.stopped != nextProps.stopped ||
      props.durationOverride != nextProps.durationOverride ||
      props.editable != nextProps.editable
    ) {
      await loadTimer(nextProps);
    }

    return null;
  }

This works as expected, functionally. However, I am getting this yellow text message in the console:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

[Unhandled promise rejection: ReferenceError: Can’t find variable:
loadTimer]

What is the issue here? Is it that I’m calling a function within getDerivedStateFromProps()? Or is the issue that it’s a promise? Or is the issue to do with the loadTimer() function itself? That function looks like this:

async loadTimer(props) {
    await Promise.all([
      new Promise((resolve) => {
        if(props.editable !== undefined) this.setState({
          editable: props.editable,
        }, resolve);
      }),
      new Promise((resolve) => {
        if(props.stopped) {
          this.setState({
            stopTime: moment(props.stopped).format('YYYY-MM-DD HH:mm:ss'),
            stopDuration: moment(props.stopped).format('HH:mm'),
          }, resolve);
        } else {
          this.setState({
            stopTime: null,
            stopDuration: null,
          }, resolve);
        }
      }),
      new Promise((resolve) => {
        if(props.stopTimeOffset && props.stopTimeOffset != Number.NaN) {
          this.setState({ stopTimeOffset: props.stopTimeOffset }, resolve);
        } else {
          this.setState({ stopTimeOffset: 0 }, resolve);
        }
      }),
      new Promise((resolve) => {
        if(props.started) {
          this.setState({
            startTime: moment(props.started).format('YYYY-MM-DD HH:mm:ss'),
            startDuration: moment(props.started).format('HH:mm'),
          }, resolve);
        } else {
          this.setState({
            startTime: null,
            startDuration: null,
          }, resolve);
        }
      })
    ]);
    
    if(!props.stopped && props.started && this.state.editable) {
      await this._startTimer();
    } else {
      if(props.durationOverride && !this.state.editable) {
        this.setState({
          duration: `${props.durationOverride}:00`,
          durationShort: props.durationOverride,
        });
      } else {
        const duration = this._getDuration();
        this.setState({
          duration: duration.long,
          shortDuration: duration.short,
        });
      }
    }
  }

>Solution :

This isn’t the kind of case that getDerivedStateFromProps is designed for. I recommend you put your code in componentDidUpdate instead:

  async componentDidUpdate(prevProps) {
    if(
      this.props.started != prevProps.started ||
      this.props.stopped != prevProps.stopped ||
      this.props.durationOverride != prevProps.durationOverride ||
      this.props.editable != prevProps.editable
    ) {
      await this.loadTimer(this.props);
    }
  }

You may find the following article from the react team useful: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading