[javascript] 매초마다 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 관점에서 시간을 다시 그리는 가장 좋은 방법은 무엇입니까?



답변

를 사용 setInterval하여 변경을 트리거해야하지만 구성 요소가 마운트 해제 될 때 타이머를 지워서 오류를 남기고 메모리 누수를 방지해야합니다.

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


답변

다음 코드는 React.js 웹 사이트에서 수정 된 예제입니다.

원본 코드는 여기에서 확인할 수 있습니다 : https://reactjs.org/#a-simple-component

class Timer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      seconds: parseInt(props.startTimeInSeconds, 10) || 0
    };
  }

  tick() {
    this.setState(state => ({
      seconds: state.seconds + 1
    }));
  }

  componentDidMount() {
    this.interval = setInterval(() => this.tick(), 1000);
  }

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

  formatTime(secs) {
    let hours   = Math.floor(secs / 3600);
    let minutes = Math.floor(secs / 60) % 60;
    let seconds = secs % 60;
    return [hours, minutes, seconds]
        .map(v => ('' + v).padStart(2, '0'))
        .filter((v,i) => v !== '00' || i > 0)
        .join(':');
  }

  render() {
    return (
      <div>
        Timer: {this.formatTime(this.state.seconds)}
      </div>
    );
  }
}

ReactDOM.render(
  <Timer startTimeInSeconds="300" />,
  document.getElementById('timer-example')
);


답변

@Waisky가 제안했습니다.

를 사용 setInterval하여 변경을 트리거해야하지만 구성 요소가 마운트 해제 될 때 타이머를 지워서 오류를 남기고 메모리 누수를 방지해야합니다.

똑같은 일을하고 싶다면 Hooks를 사용하세요 :

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

useEffect(() => {
  const interval = setInterval(() => setTime(Date.now()), 1000);
  return () => {
    clearInterval(interval);
  };
}, []);

의견에 관하여 :

내부에 아무것도 전달할 필요가 없습니다 []. time대괄호 를 전달하면 time변경 값이 변경 될 때마다 효과가 실행된다는 의미입니다 . 즉 setInterval, time변경 될 때마다 새 효과를 호출합니다. 이는 우리가 찾고있는 것이 아닙니다. 우리는 호출 할 setInterval구성 요소가 설치됩니다 때 일단 다음 setInterval호출 setTime(Date.now())1,000 초. 마지막으로 clearInterval컴포넌트가 마운트 해제 될 때 호출 합니다.

구성 요소는 time값이 time변경 될 때마다 사용한 방식에 따라 업데이트 됩니다. 즉 퍼팅과는 아무 상관이 없습니다 time[]의를 useEffect.


답변

구성 요소의 componentDidMount수명주기 메서드에서 상태를 업데이트하는 함수를 호출하는 간격을 설정할 수 있습니다.

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


답변

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>
        );
      }
    }


답변

그래서 당신은 올바른 길을 가고있었습니다. 내부 에서 변경을 트리거하도록 componentDidMount()구현하여 작업을 완료 할 수 setInterval()있지만 구성 요소 상태를 업데이트하는 방법은를 통해 수행하는 setState()것이므로 내부에서 다음 componentDidMount()을 수행 할 수 있습니다.

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

또한 위에서 제공 한 구현으로 Date.now()작동하는 것을 사용 componentDidMount()하지만 사람이 읽을 수없는 긴 숫자 업데이트를 얻을 수 있지만 기술적으로는 1970 년 1 월 1 일 이후 밀리 초 단위로 매초 업데이트되는 시간입니다. 그래서 학습 및 구현하는 것 외에, 우리는 읽기 시간을 인간이 어떻게이 시간을 읽을 수 있도록하려는 setInterval당신에 대해 배우고 싶어 new Date()하고 toLocaleTimeString()당신은 너무 좋아 구현하는 것입니다 :

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

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

constructor()함수를 제거 했는데 꼭 필요한 것은 아닙니다. 리팩터링은 constructor()함수로 사이트를 초기화하는 것과 100 % 동일 합니다.


답변

componentWillReceiveProps ()가 더 이상 사용되지 않는 React V16의 변경으로 인해 구성 요소를 업데이트하는 데 사용하는 방법론입니다. 아래 예제는 Typescript에 있으며 정적 getDerivedStateFromProps 메서드를 사용하여 Prop이 업데이트 될 때마다 초기 상태와 업데이트 된 상태를 가져옵니다.

    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>;
  }
}