2017-03-09 89 views
0

我正在使用React来呈现我的web应用程序所需的一些组件,并且我有一个带有播放和停止按钮的计时器。我从获取请求中检索所有时间记录,并且每次更改我的组件时都要重新渲染组件,我该怎么做?原始ReactJS更新属性

我的一切工作,但有一个简单的setInterval来调用this.forceUpdate(功能),但给我的警告:

警告:forceUpdate(...):只能更新一安装或安装部件。这通常意味着您在卸载的组件上调用了forceUpdate()。这是一个没有操作。请检查TimerBox组件的代码。

我的组件:

var TimerBox = React.createClass({ 
    displayName: 'TimerBox', 

    updateTime: function() { 
     getTime(); 
     this.forceUpdate(); 
     this.props.records = allRecords(); // get all time records 
    }, 

    componentDidMount: function() { 
     setInterval(this.updateTime, 1000); // set interval to each second 
    }, 

    render: function() { 
     this.props.records = allRecords(); 
     return (
     React.createElement('div', { className: 'main-timer-box' }, 
      React.createElement('div', { className: 'timer-box' }, hours + ' hours, ' + minutes + ' minutes and ' + seconds + ' seconds', 
      React.createElement(ControlButton, null)), 
      React.createElement('hr', null) 
     ) 
    ); 
    } 
    }); 

我是新来reactjs和我开始使用无JSX,巴贝尔或反应的WebPack,我不wan't改变整个代码,现在。

我只是想知道我可以声明一个属性,然后在每次改变值时使属性调用重新渲染。

谢谢。

回答

3

你应该更新组件状态,它会自动重新渲染组件。此外,您必须清除componentWillUnmount生命周期方法中的超时,以确保仅在组件尚未卸载时才调用setState

updateTime: function() { 
     getTime(); 
     this.setState({ 
     records: yourRecordsData 
     }) 
    } 
    componentDidMount: function() { 
     this.myTimer = setInterval(this.updateTime, 1000); // set interval to each second 
    }, 
    componentWillUnmount: function() { 
     clearInterval(this.myTimer) 
    }, 

现在你可以使用在这样的渲染功能状态数据:this.state.records

请注意,当React组件的状态已更新或父组件已被重新渲染时,它们会重新渲染。你不应该设置组件自己的道具 - 你只能在子组件上设置道具。一般来说,你不应该使用forceUpdate(老实说你几乎不需要它)。检查反应docs以获取更多详细信息并解释为什么应该避免forceUpdate

+0

工作更新我的组件,谢谢。但是我现在对setState有同样的警告“......只能更新挂载或挂载组件,这通常意味着你在卸载的组件上调用了setState()......”似乎问题在于调用updateTime函数 –

+0

这是因为'setState'在超时时被调用,当它实际上被调用时,你的组件已被卸载。为避免这种情况,你必须在'componentWillUnmount'生命周期方法中清除超时,以确保'setState'仅在组件未被卸载时才被调用 –

+0

请参阅更新的答案或使用@finalfreq解决方案:) –

2

这里的问题在于你有一个setInterval,它没有关于组件何时从DOM卸载的概念。因此,一旦该组件卸载,setInterval函数无论如何会触发并尝试更新导致此问题的未安装组件的状态。

要解决该警告,你只需要做:

componentDidMount: function() { 
    this.interval = setInterval(this.updateTime, 1000); // set interval to each second 
    }, 

componentWillUnmount: function() { 
    clearInterval(this.interval); 
} 

这样做是设置this.interval在区间的定时器ID,然后使用componentWillUnmount生命周期的方法,我们要确保我们清除定时器方式在组件卸载后代码不会被执行。

+0

这真的解决了我的问题,谢谢你的解释和帮助,我很长一段时间都在处理这个问题!虽然你的答案帮助我解决了我的prolbem问题,但我需要让Bartek Fryzowicz成为正确的答案才是公平的,因为我的问题是关于如何在不必调用forceUpdate()的情况下更新属性。再次感谢你。 –

+0

没问题!很高兴有你照顾! – finalfreq