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