Home > database >  Can't find variable error in `getDerivedStateFromProps`
Can't find variable error in `getDerivedStateFromProps`

Time:03-31

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:

[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,
        });
      }
    }
  }

CodePudding user response:

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

  • Related