Javascript 反应:告诉子组件“反应”;“重新初始化”;即使传递的道具相同
我有一个MyComponent来呈现计时器组件。我当前的设置如下: MyComponent.render:Javascript 反应:告诉子组件“反应”;“重新初始化”;即使传递的道具相同,javascript,reactjs,Javascript,Reactjs,我有一个MyComponent来呈现计时器组件。我当前的设置如下: MyComponent.render: render () { return <Timer time={this.state.time} lag={this.lag || 0} /> } render(){ 返回 } 计时器: class Timer extends Component { constructor(props) { super(props); this.state = {
render () {
return <Timer time={this.state.time} lag={this.lag || 0} />
}
render(){
返回
}
计时器:
class Timer extends Component {
constructor(props) {
super(props);
this.state = {
time: this.props.time,
};
}
startTimer = (duration) => {
if (duration > 0){
this.on = true;
let timer = duration * 1000 + this.props.lag;
var s = setInterval(() => {
this.setState({time: Math.round(timer/1000)});
timer = timer - 500;
if (timer <= 0) {
this.on = false;
clearInterval(s);
}
}, 500);
}
}
componentDidMount = () => {
this.startTimer(this.props.time);
}
render() {
return (
<div className="Timer-container">
<div className="Timer-value">{this.state.time}</div>
</div>
);
}
}
类计时器扩展组件{
建造师(道具){
超级(道具);
此.state={
时间:这个。道具。时间,
};
}
起始时间=(持续时间)=>{
如果(持续时间>0){
this.on=true;
让定时器=持续时间*1000+this.props.lag;
var s=setInterval(()=>{
this.setState({time:Math.round(timer/1000)});
定时器=定时器-500;
中频(定时器){
this.startTimer(this.props.time);
}
render(){
返回(
{this.state.time}
);
}
}
如您所见,当计时器初始化时,它立即开始倒计时。在随后的MyComponent
渲染中,我想重新启动计时器
,即使时间
道具没有改变。换句话说,我想在每次渲染时都“重新初始化”。我该如何实现这一点
- 间隔(以便您可以清除它)
- 或当前时间(因此可以将其设置为初始值)
shouldrererender
属性传递给组件,然后在组件内部检查此属性:
// -- inside MyComponent
render () {
return <Timer
time={ this.state.time }
lag={ this.lag || 0 }
shouldRerender={ {/* just an empty object */} } />;
}
// -- inside Timer
componentDidUpdate(prevProps, prevState, snapshot) {
if( prevProps.shouldRerender !== this.props.shouldRerender ){
clearInterval( this.state.interval );
this.startTimer( this.props.time );
}
}
/--MyComponent内部
渲染(){
返回;
}
//--内部定时器
componentDidUpdate(prevProps、prevState、快照){
if(prevProps.shouldRerender!==this.props.shouldRerender){
clearInterval(this.state.interval);
this.startTimer(this.props.time);
}
}
对我来说,这看起来有点“脏”。更干净的方法是将一些状态传递给shouldRerender
,该状态在每次更新时都会发生变化(例如,只是数量不断增加)
<>但是,我认为检查父渲染的方法是<强>不是反应方式< /强>。我个人认为,如果一个组件渲染或没有实现细节(我不知道这是不是正确的话),也就是说,我不在乎什么时候反应决定渲染,我只关心道具和状态(基本上)。
我建议您考虑一下什么是“因果关系”,您想重置计时器的原因是什么。可能父对象的重新渲染只是其他原因的结果,您也可以使用这些原因重置时间
下面是一些我能想象到的对用例有用的不同概念:
- 不使用一次性实例,但在需要时在父级内部销毁和创建,也可以使用道具
- 使用(如
)或(如withTimer
),注入useTimer
函数(另外创建一个单独的reset()
组件)TimerView
- 将
状态保持在time
,将MyComponent
和time
传递到onChange
组件(Timer
),然后{this.setState({time:time});}}/>
和MyComponent
都可以设置/重置时间Timer
render()
中调用函数?@Justinas我不确定您的意思;您能详细说明一下吗?内部render:clearInterval(this.s);this.startTimer(1000)
您不想将其放入render()中
,因为它会在每次本地状态更改时调用函数,所以我认为您可以在componentWillReceiveProps
中调用函数,它会跳过本地状态,但只侦听父级重新渲染解决方案您可以将时间
包装到对象中,每次您想要重新启动计时器时,您都会传递一个新对象,甚至是同时time={value:500}
在组件中读取为props.time.value
。您可能需要重构代码,以便停止旧计时器(当然,如果您想停止它的话)
// -- inside MyComponent
render () {
return <Timer
time={ this.state.time }
lag={ this.lag || 0 }
shouldRerender={ {/* just an empty object */} } />;
}
// -- inside Timer
componentDidUpdate(prevProps, prevState, snapshot) {
if( prevProps.shouldRerender !== this.props.shouldRerender ){
clearInterval( this.state.interval );
this.startTimer( this.props.time );
}
}