设置状态后重新渲染状态

时间:2019-03-25 14:19:15

标签: javascript reactjs axios

我想获取数据,如果获取时出错。我想等待1000秒,然后再次获取数据。

问题在于在方法settingTimeout()中this.setState({timerStatus:true});我期望重新渲染整个应用程序并在console.log中渲染超时。但是由于某种原因,它没有这样做。我尝试在setTimeout()中使用this.forceUpdate();没有太多的运气。 React similiar example

this.state = {
      retryTimer: 1000,
      timerStatus: false,
    }
  }
  componentDidMount(){
    if(this.state.timerStatus){
      console.log('timeout');
    }
    this.newGame();
  }

  newGame =() => {
    Axios.get(
      this.state.apiBase + 'nexGame',
      this.state.headers
    )
    .then(response =>{
     console.log(response)
      }
    })
    .catch(error =>{
      this.settingTimeout();
    })
  }
  settingTimeout = () =>{
    this.setState({timerStatus: true});
    if(this.state.retryTimer === 0){
      this.newGame();
    }
  }

2 个答案:

答案 0 :(得分:0)

如果前一个呼叫失败,您似乎想每1s打一次电话,对吗?

我不确定您是否需要重新渲染应用程序才能执行此操作。如果您想重新进行此调用,可以将react生命周期与组件https://reactjs.org/docs/react-component.html#updating

一起使用

与:

shouldComponentUpdate(nextProps, nextState) {
  if(this.nextState.timerStatus = true) { 
    setState({ timerStatus: false });
    this.newGame();
}

并在函数setTimeout上设置超时,当传递1s时,将timerStatus的状态更改为true。 React将监视此事件,将timerStatus设置为false并重新进行调用。如果通话正常,您将得到答案;否则,您将再次等待1秒钟并重新拨打电话,等等。

答案 1 :(得分:0)

您可以尝试执行以下操作(说明在小提琴下):

let counter = 0;

class App extends React.Component {
    timer;
    
    constructor(props) {
        super(props);
        
        this.state = {
            data: "",
            loading: true,
            fetchError: false            
        }
    }
    
    componentDidMount() {
        /* Simulating a fetch with setTimeout. */
        const random = Math.floor(Math.random() * 1000) + 100;
        
        setTimeout(() => {
            /* Here you would write .then(). */
            if (counter === 2) {
                this.setState({loading: false});
            }
            
            /* Here you would write .catch(). */
            if (counter === 0) {
                this.setState({fetchError: true});
                this.timer = setInterval(this.handleFetch, 1000);
            }
            
            counter++;
        }, random);
    }
    
    handleFetch = () => {
        /* Simulating a fetch with setTimeout. */
        const random = Math.floor(Math.random() * 1000) + 100;
        setTimeout(() => {
            /* This would be the then(), where you save the data. */
            if (counter === 2) {
                clearInterval(this.timer);
                this.setState({loading: false, fetchError: false, data: "YES!!"})
            }
            
            /* In this case, if the fetch fails, you do nothing. */
                                  
            counter++;
        }, random);
    }
    
    render() {
        const {fetchError, loading, data} =  this.state;
        return (
            <React.Fragment>
                {loading && fetchError && <p>Error in Fetch</p>}
                {loading && !fetchError && <p>Loading</p>}
                {!loading && !fetchError && <p>{this.state.data}</p>}
           </React.Fragment>
        );
    }
}

ReactDOM.render(<App />, document.getElementById('root'));
@import url(https://fonts.googleapis.com/css?family=Montserrat);

body {
    font-family: 'Montserrat', sans-serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id='root'></div>

首先,我使用setTimeout模拟提取。此外,为了模拟提取错误,我使用了counter变量:当变量达到值2时,则认为提取正确,否则认为失败。
说,这是怎么回事?在componentDidMount中运行您的第一个提取操作:而不是if (counter === 2),您应该编写您的提取操作的.then()(因此,在正确运行时)。在该回调中,您只需将this.state.loading设置为false
否则,您应该编写if (counter === 0)语句,而不是catch():在此过程中,您将创建一个interval,每个handleFetch()都调用1000ms函数。请注意,在这种情况下,您将this.state.fetchError设置为true:这样可以为用户提供更好的反馈。

现在,在handleFetch()内执行提取:再次,如果正确结束,则可以将this.state.loadingthis.state.fetchError设置为false,并将数据保存到状态。 否则,您只需等待另一个1000ms进行下一次提取。