【问题标题】:Updating State with Variable in React在 React 中使用变量更新状态
【发布时间】:2019-01-29 10:26:11
【问题描述】:

我正在尝试破解我的状态未更新的特殊问题。 我有一个通过 Axios 调用 NASA api 的函数,它运行良好。目前datePicked 状态默认为空,这意味着 GET 请求默认为当前日期。我要添加生成随机日期的功能(函数onRandomDateClick),一切正常。

然后我想用生成的日期更新datePicked的状态,然后运行保存axios请求的onImageGet函数。

初始状态

  class Photo extends Component {
    state = {
      apiUrl: 'XXXXXXXX',
      apiKey: 'XXXXXXXX',
      image: null,
      imgChecked: false,
      datePicked: ""
    };

生成随机日期、记录变量和状态。状态当前显示为空白。 this.setState 不起作用。

    onRandomDateClick = (e) => {
      function randomDate(start, end) {
        return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
      }
      let randomDateResult = randomDate(new Date(2012, 0, 1), new Date())
      let datePicked = randomDateResult.toISOString().slice(0,10);
      this.setState({datePicked})
      console.log("variable is " + datePicked);
      console.log("state is " + this.state.datePicked);
      this.onImageGet();
    }

Axios 在此处调用状态

    onImageGet = e => {
      axios.get(`${this.state.apiUrl}?api_key=${this.state.apiKey}&date=${this.state.datePicked}`)
      //response always starts res.data
          .then(res => {
            const image = res.data;
            this.setState({ image })
          })
          this.setState({imgChecked: true})
    }


    render() {
      ...blah blah...
      return (
        <div className="photo">        

         ... blah blah blah ...
        </div>

      );
    }
  }

【问题讨论】:

  • 您实际上还没有设置状态。 this.setState({parameter: value}) 是正确的语法。
  • 另一种方法是使用redux和redux-axios-middleware进行异步操作。
  • js 是异步的。你应该做这样的事情。 gist.github.com/nazrdogan/1167c9683a66f038516f527184b024c3
  • @KenoClayton 我的印象是,如果 var 名称和状态相同,可以这样做吗?这不正确吗?
  • 我实际上不确定,我从未见过这种实现,所以我可能会弄错。

标签: javascript reactjs


【解决方案1】:

Js 正在为 http 调用异步工作。因为 React setState 是异步的。你应该这样做。

onRandomDateClick = (e) => {
      function randomDate(start, end) {
        return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
      }
      let randomDateResult = randomDate(new Date(2012, 0, 1), new Date())
      let datePicked = randomDateResult.toISOString().slice(0,10);
      this.setState({datePicked},() => {
        this.onImageGet();
      })
    }
    
    onImageGet = e => {
      axios.get(`${this.state.apiUrl}?api_key=${this.state.apiKey}&date=${this.state.datePicked}`)
      //response always starts res.data
          .then(res => {
            const image = res.data;
            this.setState({ image, imgChecked: true })

          })
        
    }
    render() {
      ...blah blah...
      return (
        <div className="photo">        

         ... blah blah blah ...
        </div>

      );
    }
  }

【讨论】:

  • 异步的不是 JS。就是setState 是异步的。
  • 我的意思是http调用。也许它具有误导性。我会编辑:)
【解决方案2】:

问题在于setState 是异步的,所以当您在设置状态后立即调用onImageGet 时,状态尚未更新,您访问的是前一个状态。

您可以使用setState 支持的回调方法,该方法在状态更新后调用。

this.setState({datePicked}, this.onImageGet)

或更常见的模式是检查componentDidUpdate 中的相关更改并在那里调用this.onImageGet

  class Photo extends Component {
    state = {
      apiUrl: 'XXXXXXXX',
      apiKey: 'XXXXXXXX',
      image: null,
      imgChecked: false,
      datePicked: ""
    };


    onRandomDateClick = (e) => {
      function randomDate(start, end) {
        return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
      }
      let randomDateResult = randomDate(new Date(2012, 0, 1), new Date())
      let datePicked = randomDateResult.toISOString().slice(0,10);
      this.setState({datePicked})
      console.log("variable is " + datePicked);
      console.log("state is " + this.state.datePicked);
    }

    onImageGet = e => {
      axios.get(`${this.state.apiUrl}?api_key=${this.state.apiKey}&date=${this.state.datePicked}`)
      //response always starts res.data
          .then(res => {
            const image = res.data;
            this.setState({ image })
          })
          this.setState({imgChecked: true})
    }

    componentDidUpdate(prevProps, prevState){
      if (prevState.datePicked !== this.state.datePicked){
        this.onImageGet();
      }
    }

    render() {
      ...blah blah...
      return (
        <div className="photo">        
         ... blah blah blah ...
        </div>

      );
    }
  }

【讨论】:

  • 谢谢,看看解决方案的不同实现真的很有用。
猜你喜欢
  • 1970-01-01
  • 2020-04-11
  • 2016-11-10
  • 2020-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-11
  • 2020-12-19
  • 2019-08-30
相关资源
最近更新 更多