反应渲染正在使用新旧状态值,而不仅仅是新值
Posted
技术标签:
【中文标题】反应渲染正在使用新旧状态值,而不仅仅是新值【英文标题】:react render is using old and new state values, instead of just the new value 【发布时间】:2019-11-25 01:40:40 【问题描述】:我正在尝试创建一个时钟,用户可以在其中选择一个位置并在屏幕上呈现当前时间。该代码适用于第一个用户按钮单击。但是,如果他们随后选择了不同的位置,则小时状态值应更新为新值。它这样做了,但是 react 也将旧值渲染到屏幕上。因此,时钟上的小时在两个不同的值之间闪烁。谁能解释为什么会发生这种情况,以及我如何只能在用户第二次点击后显示新的小时值?
import React from 'react';
import ReactDOM from 'react-dom';
import ButtonClick from './Components/UserInputs.js'
//define global time difference matrix
var timeDiffMat= [0, 6, 1, 2, -5];
class Clock extends React.Component
constructor(props)
super(props);
//this.userInput = this.userInput.bind(this);
this.adjustForLocation = this.adjustForLocation.bind(this);
this.tick = this.tick.bind(this);
this.state = CityfromChild: "", hours:0, minutes: 0, seconds: 0,
test:'';
//this.initialSetTime = this.initialSetTime.bind(this);
this.setTime = this.setTime.bind(this);
adjustForLocation(citySelected, numberOfClicks)
function getTimeDiff ()
if (citySelected == "Local Time") return timeDiffMat[0]
if (citySelected =="Tokyo") return timeDiffMat[1]
if (citySelected =="Cape Town") return timeDiffMat[2]
if (citySelected =="Moscow")return timeDiffMat[3]
if (citySelected =="New York") return timeDiffMat[4]
this.timeDiff = getTimeDiff(citySelected)
this.tick(this.timeDiff)
tick(timeDiff)
setInterval(()=> this.setTime(timeDiff), 1000)
setTime(timeDiff)
this.setState(
seconds: new Date().getSeconds(),
minutes: new Date().getMinutes()
);
this.setState(hours: timeDiff + new Date().getHours() )
// unmount Clock Component and invalidate timer
componentWillUnmount()
clearInterval(this.interval);
render()
return (
<div className="border">
<h3> Choose a city </h3>
<div className="button-container">
<ul>
<li> <ButtonClick getTimeOnClick =
this.userInput adjustHoursForCity = this.adjustForLocation
buttonLabel= "Local Time"/> </li>
<li> <ButtonClick getTimeOnClick =
this.userInput adjustHoursForCity = this.adjustForLocation
buttonLabel= "Cape Town"/> </li>
<li> <ButtonClick getTimeOnClick =
this.userInput adjustHoursForCity = this.adjustForLocation
buttonLabel= "Moscow"/> </li>
<li> <ButtonClick getTimeOnClick =
this.userInput adjustHoursForCity = this.adjustForLocation
buttonLabel= "New York"/> </li>
<li> <ButtonClick getTimeOnClick =
this.userInput adjustHoursForCity = this.adjustForLocation
buttonLabel= "Tokyo"/> </li>
<button>this.state.CityfromChild</button>
<button>this.state.test</button>
</ul>
</div>
<div>this.state.hours:this.state.minutes:
this.state.seconds </div>
</div>
);
【问题讨论】:
为什么你连续两次调用 setState 而不包括第一个 setState 中的小时数?也许这已经可以解决您的问题 我也试过这个,但我仍然遇到同样的问题 嗯,好吧,但你还是不要那样做,我再看看 【参考方案1】:当您更新时间时,您会创建一个新的setInterval
,但不会清除旧的。因此,您将有多个setInterval
,每个设置时间使用不同的timeDiff
。
尝试类似:
tick(timeDiff)
if (this.timer)
clearInterval(this.timer);
this.timer = setInterval(() => this.setTime(timeDiff), 1000)
【讨论】:
所以你是说它同时运行setInterval
的两个实例?
是的,tick
函数会新建一个,所以每次点击按钮设置timeDiff都会创建一个
@SeanBarker 我添加了一些可以解决问题的代码。【参考方案2】:
您应该将setTimeInterval
绑定到您的组件,例如this.mySetTimeInterval = setTimeInterval(() => );
在其他任何地方你都可以停止运行间隔:
clearInterval(this.mySetTimeInterval)
【讨论】:
为什么我需要将区间绑定到它的组件?只是为了让我以后可以调用它来清除它吗? 组件卸载时,间隔会一直在后台运行,导致内存泄漏。如果绑定到组件,可以在componentWillUnmount
中清除【参考方案3】:
您的代码中没有this.interval
,就像componentWillUnmount
中使用的那样,在函数tick
中,我相信您想将setInterval 调用的结果存储在一个名为interval 的变量中。正如@rebecca 所说,您可能应该使用
setTime(timeDiff)
setState(/* To avoid race conditions */ function()
return
seconds: new Date().getSeconds(),
minutes: new Date().getMinutes(),
hours: timeDiff + new Date().getHours()
)
tick(timeDiff)
this.interval = setInterval(() => this.setTime(timeDiff), 1000)
为了避免竞争条件
【讨论】:
以上是关于反应渲染正在使用新旧状态值,而不仅仅是新值的主要内容,如果未能解决你的问题,请参考以下文章