-
카테고리
-
세부 분야
프론트엔드
-
해결 여부
해결됨
비동기 작업 해제에 대해
23.05.06 02:43 작성 23.05.06 03:03 수정 조회수 228
0
interval
componentDidMount() {
this.interval = setInterval(this.changeHand, 100)
}
componentDidUpdate() {
}
componentWillUnmount() {
clearInterval(this.interval)
}
onClickBtn = (choice) => {
clearInterval(this.interval)
const {imgCoord} = this.state
const myScore = scores[choice]
const cpuScore = scores[computerChoice(imgCoord)]
const diff = myScore - cpuScore
if (diff === 0) {
this.setState({
result: '비겼습니다!'
})
} else if ([-1, 2].includes(diff)) {
this.setState((prevState) => {
return {
result:'이겼습니다!',
score: prevState.score + 1,
}
})
} else {
this.setState((prevState) => {
return {
result: '졌습니다.',
score: prevState.score - 1
}
})
}
setTimeout(() => {
this.interval = setInterval(this.changeHand, 100);
}, 2000);
}
render() {
const {result, score, imgCoord} = this.state;
return (
<>
<div id="computer" style={{ background: `url(https://en.pimg.jp/023/182/267/1/23182267.jpg) ${imgCoord} 0px` }} />
<div>
<button id="rock" className="btn" onClick={()=>this.onClickBtn('바위')}>바위</button>
<button id="scissor" className="btn" onClick={()=>this.onClickBtn('가위')}>가위</button>
<button id="paper" className="btn" onClick={()=>this.onClickBtn('보')}>보</button>
</div>
<div>{result}</div>
<div>현재 {score}점</div>
</>
강의에서 제로초님이 가위바위보 컴포넌트는 제거를 안하기 때문에 componentWillUnmount()를 넣으나 안넣으나 상관이 없다는식으로 얘기를 했습니다.
그러나 componentWillUnmount()에 clearInterval를 안넣게되면 componentDidMount()에서 생성된 this.interval라는 비동기작업이 onClickBtn 함수에서 clearInterval로 해제가 안됩니다.
왜 그런지 이유가 궁금합니다.
답변을 작성해보세요.
0
조현영
지식공유자2023.05.06
강의에서 제로초님이 가위바위보 컴포넌트는 제거를 안하기 때문에 componentWillUnmount()를 넣으나 안넣으나 상관이 없다는식으로 얘기를 했습니다.
제가 언제 이런 말을 했나요..? 했다 해도 그 맥락이 아니었을텐데요?
setInterval이 있으면 당연히 componentWillUnmount에서 해제해야 합니다.
Bell Vise
질문자2023.05.06
5-3. 가위바위보 만들기에서 9분쯤에 componentWillUnmount() 넣으나 안넣으나 체감하기 힘들다. 가위바위보 컴포넌트를 제거를 안하기 때문인데 자식컴포넌트가 됐을 때는 꼭 넣어줘야 메모리 누수 문제를 안겪을 수 있다. 이렇게 말씀하셨는데 말씀대로
componentWillUnmount()는 컴포넌트가 제거되기 직전에 실행되니까 가위바위보 컴포넌트는 제거되는 경우가 브라우저를 종료했을 때 말고는 없기 때문에 componentWillUnmount() 없애고 그냥 setInterval을 onClickBtn함수에서 clearInterval 해도 이론적으로 되지 않을까요?
근데 componentWillUnmount()는 실행될 일이 없음에도 왜 언마운트에 clearInterval을 해야하는지 궁금합니다. 또 언마운트에 clearInterval을 안하게 되면 onClickBtn함수로는 왜 비동기 작업이 해제가 안되는지 궁금해요.
조현영
지식공유자2023.05.06
근데 componentWillUnmount()는 실행될 일이 없음에도 왜 언마운트에 clearInterval을 해야하는지 궁금합니다.
네 브라우저를 종료할 때를 제외하고는 unmount가 될 일이 없는 컴포넌트에서는 componentWillUnmount에서 clearInterval을 안 해도 됩니다. 다만 항상 unmount에서 clear하는 습관을 들이는 게 좋습니다.
그냥 setInterval을 onClickBtn함수에서 clearInterval 해도 이론적으로 되지 않을까요?
onClickBtn함수에서는 왜 clearInterval을 하나요? 지금 unmount쪽과 완전히 다른 맥락으로 이야기하시는 건가요? 가위바위보가 돌아가는 걸 멈추는 걸 말씀하시는 거면 onClickBtn에서 clearInterval하는 게 맞습니다. unmount쪽은 아예 컴포넌트를 언마운트할 때 clear하기위해서 하는 거고요.
언마운트에 clearInterval을 안하게 되면 onClickBtn으로는 비동기 작업이 해제가 왜 안되는지 궁금해요.
해제가 됩니다. 언마운트랑 상관이 없어요.
지금 onClickBtn에서 clearInterval하는 것과 componentWillUnmount에서 clearInterval하는 것이 왜 한 질문에 같이 나오는지 이해를 못 하겠습니다.
Bell Vise
질문자2023.05.06
gif 사진을 가져와봤습니다.
onClickBtn 함수에 clearInterval이 있음에도 componentWillUnmount()에 clearInterval를 안쓰게 되면 onClickBtn 함수에 clearInterval은 작동이 안됩니다.
소스코드 전문입니다.
import React, { Component } from 'react'
// 클래스의 경우 -> constructor -> render -> ref -> componentDidMount
// (setState/props 바뀔때) -> shouldComponentUpdate(true) -> render -> componentDidUpdate
// 부모가 나를 없앴을 때 -> componentWillUnmount -> 소멸
const rspCoords = {
바위: '0',
가위: '-142px',
보: '-284px',
}
const scores = {
가위: 1,
바위: 0,
보: -1,
}
const computerChoice = (imgCoord) => {
return Object.entries(rspCoords).find(function(v) {
return v[1] === imgCoord;
})[0]
}
class RPSClass extends Component {
state = {
result : '',
imgCoord: rspCoords.바위,
score: 0,
}
interval
componentDidMount() {
this.interval = setInterval(this.changeHand, 100)
}
componentDidUpdate() { // 리렌더링 후
}
changeHand = () =>{ const {imgCoord} = this.state
if(imgCoord === rspCoords.바위) {
this.setState({
imgCoord:rspCoords.가위
})
} else if (imgCoord === rspCoords.가위) {
this.setState({
imgCoord: rspCoords.보,
})
} else if (imgCoord === rspCoords.보) {
this.setState({
imgCoord:rspCoords.바위
})
}
}
onClickBtn = (choice) => {
clearInterval(this.interval)
const {imgCoord} = this.state
const myScore = scores[choice]
const cpuScore = scores[computerChoice(imgCoord)]
const diff = myScore - cpuScore
if (diff === 0) {
this.setState({
result: '비겼습니다!'
})
} else if ([-1, 2].includes(diff)) {
this.setState((prevState) => {
return {
result:'이겼습니다!',
score: prevState.score + 1,
}
})
} else {
this.setState((prevState) => {
return {
result: '졌습니다.',
score: prevState.score - 1
}
})
}
setTimeout(() => {
this.interval = setInterval(this.changeHand, 100);
}, 2000);
}
render() {
const {result, score, imgCoord} = this.state;
return (
<>
<div id="computer" style={{ background: `url(https://en.pimg.jp/023/182/267/1/23182267.jpg) ${imgCoord} 0px` }} />
<div>
<button id="rock" className="btn" onClick={()=>this.onClickBtn('바위')}>바위</button>
<button id="scissor" className="btn" onClick={()=>this.onClickBtn('가위')}>가위</button>
<button id="paper" className="btn" onClick={()=>this.onClickBtn('보')}>보</button>
</div>
<div>{result}</div>
<div>현재 {score}점</div>
</>
)
}
}
export default RPSClass
조현영
지식공유자2023.05.06
애초에 componentWillUnmount는 실행도 되지 않으므로 여기 코드가 바뀐다고 해서 RSPClass 동작에 영향이 갈 수가 없습니다.
답변 1