每秒更新React组件

我一直在玩React,并具有以下仅显示Date.now()在屏幕上的时间组件

import React, { Component } from 'react';

class TimeComponent extends Component {
  constructor(props){
    super(props);
    this.state = { time: Date.now() };
  }
  render(){
    return(
      <div> { this.state.time } </div>
    );
  }
  componentDidMount() {
    console.log("TimeComponent Mounted...")
  }
}

export default TimeComponent;

从React的角度来看,使该组件每秒更新以重新绘制时间的最佳方法是什么?

西里Sam2020/03/12 15:13:04

@Waisky建议:

您需要使用setInterval来触发更改,但是还需要在组件卸载时清除计时器,以防止它留下错误和内存泄漏:

如果您想做同样的事情,请使用Hooks:

const [time, setTime] = useState(Date.now());

useEffect(() => {
  const interval = setInterval(() => setTime(Date.now()), 1000);
  return () => {
    clearInterval(interval);
  };
}, []);
猿前端前端2020/03/12 15:13:04

在组件的componentDidMount生命周期方法中,您可以设置间隔来调用更新状态的函数。

 componentDidMount() {
      setInterval(() => this.setState({ time: Date.now()}), 1000)
 }
小宇宙神无2020/03/12 15:13:04

Owing to changes in React V16 where componentWillReceiveProps() has been deprecated, this is the methodology that I use for updating a component. Notice that the below example is in Typescript and uses the static getDerivedStateFromProps method to get the initial state and updated state whenever the Props are updated.

    class SomeClass extends React.Component<Props, State> {
  static getDerivedStateFromProps(nextProps: Readonly<Props>): Partial<State> | null {
    return {
      time: nextProps.time
    };
  }

  timerInterval: any;

  componentDidMount() {
    this.timerInterval = setInterval(this.tick.bind(this), 1000);
  }

  tick() {
    this.setState({ time: this.props.time });
  }

  componentWillUnmount() {
    clearInterval(this.timerInterval);
  }

  render() {
    return <div>{this.state.time}</div>;
  }
}
泡芙阿飞斯丁2020/03/12 15:13:04
class ShowDateTime extends React.Component {
   constructor() {
      super();
      this.state = {
        curTime : null
      }
    }
    componentDidMount() {
      setInterval( () => {
        this.setState({
          curTime : new Date().toLocaleString()
        })
      },1000)
    }
   render() {
        return(
          <div>
            <h2>{this.state.curTime}</h2>
          </div>
        );
      }
    }
小小猿2020/03/12 15:13:04

So you were on the right track. Inside your componentDidMount() you could have finished the job by implementing setInterval() to trigger the change, but remember the way to update a components state is via setState(), so inside your componentDidMount() you could have done this:

componentDidMount() {
  setInterval(() => {
   this.setState({time: Date.now()})    
  }, 1000)
}

Also, you use Date.now() which works, with the componentDidMount() implementation I offered above, but you will get a long set of nasty numbers updating that is not human readable, but it is technically the time updating every second in milliseconds since January 1, 1970, but we want to make this time readable to how we humans read time, so in addition to learning and implementing setInterval you want to learn about new Date() and toLocaleTimeString() and you would implement it like so:

class TimeComponent extends Component {
  state = { time: new Date().toLocaleTimeString() };
}

componentDidMount() {
  setInterval(() => {
   this.setState({ time: new Date().toLocaleTimeString() })    
  }, 1000)
}

Notice I also removed the constructor() function, you do not necessarily need it, my refactor is 100% equivalent to initializing site with the constructor() function.

Gil村村2020/03/12 15:13:04

您需要使用setInterval来触发更改,但是还需要在组件卸载时清除计时器,以防止它留下错误和内存泄漏:

componentDidMount() {
  this.interval = setInterval(() => this.setState({ time: Date.now() }), 1000);
}
componentWillUnmount() {
  clearInterval(this.interval);
}