저번시간 숙제 : Detail 페이지 방문 후 2초 후에 alert 박스가 사라지게 해보십시오.
저번시간 내드린 숙제부터 해결한 후 useEffect 훅의 사용법 하나만 더 알아봅시다.
숙제는.. alert 박스가 사라지게 하는 것이 문제입니다.
"근데 사라지게 하는 건 배운 적이 없는 것 같은데.." 는 실은 배웠습니다.
예전에 모달창 이런거 만들 때 [리액트에서 UI 만드는 법]을 설명해드린 적이 있습니다.
[UI 만드는 법]에 의해 alert 박스를 다시 만들어놓으시면 쉽게 UI를 사라지게 만들 수 있습니다.
일단 UI 어떻게 만든다고 했습니까
UI 보이고 안보이고의 상태를 state로 저장해둠 (true/false 이런걸로)
state가 true일 때만 UI를 보여준다고 if문을 짜둠
그래서 이런 법칙에 의해 alert를 다시 만들어주시면 됩니다. 그럼 쉽게쉽게 UI 끄기 켜기 가능
그럼 진짜 만들어보겠습니다.
function Detail() {
let [ alert, alert변경 ] = useState(true);
useEffect(() => {
});
return (
<HTML많은곳 />
{
alert === true
? (
<p>재고가 얼마 남지 않았습니다</p>
</div>)
: null
}
)
}
▲ state를 만들고 state에 의해서 UI를 보여주도록 if문을 완성했습니다.
여러분도 기존에 있던 alert UI를 이렇게 바꾸시면 되겠습니다.
Q. 세상에 모든 UI는 그럼 이렇게 만들어야하나요?
A. 항상 보이는 UI가 아니라 껐다키는 기능이 필요하면 다 이렇게 만듭니다.
숙제 : Detail 페이지 방문 후 2초 후에 alert 박스가 사라지게 해보십시오.
그럼 이제 숙제의 답을 쉽게 낼 수 있습니다.
그냥 Detail 컴포넌트 로드 후 2초 후에 alert라는 state를 false로 만들어주면 되는 것이군요.
그럼 useEffect()안에 이런 식으로 개발하면 되겠군요.
(Detail.js 파일)
function Detail(){
let [ alert, alert변경 ] = useState(true);
useEffect(()=>{
let 타이머 = setTimeout(()=>{ alert변경(false) }, 2000);
});
return (
<HTML많은곳/>
{
alert === true
? (
<p>재고가 얼마 남지 않았습니다</p>
</div>)
: null
}
)
}
▲ useEffect 안에 2초 타이머를 추가했고 2초 후에 alert 라는 state를 false로 변경하라고 시켰습니다.
끝!
잉 근데 Detail 컴포넌트가 업데이트될 때도 저거 useEffect 실행됨
원래 그렇습니다. useEffect()는 컴포넌트 등장 & 업데이트가 되고나서 항상 실행됩니다.
컴포넌트 업데이트시 진짜 실행되는지 실험해보도록 합시다.
(Detail.js 파일)
function Detail(){
let [ alert, alert변경 ] = useState(true);
let [inputData, inputData변경] = useState('');
useEffect(()=>{
let 타이머 = setTimeout(()=>{ alert변경(false) }, 2000);
});
return (
<HTML많은곳/>
{ inputData }
<input onChange={ (e)=>{ inputData변경(e.target.value) }}/>
{
alert === true
? (<div className="my-alert2">
<p>재고가 얼마 남지 않았습니다</p>
</div>)
: null
}
)
}
▲ 세줄을 추가했습니다. 1. inputData라는 빈 state를 하나 만들었습니다.
태그를 만들어서 거기 문자가 입력될 때마다 inputData라는 state에 저장되게 했습니다.
그리고 그 inputData를 구경하기 위해서 { inputData }데이터바인딩했습니다.
을 왜 만들었냐고요? 그냥 Detail 컴포넌트 강제로 업데이트 시키려고 만들었습니다.
에다가 뭔가 입력하면 계속 Detail 컴포넌트가 재렌더링됩니다. (업데이트됨)
그럼 에다가 뭔가 입력할 때마다 useEffect() 이것도 실행되겠죠?
근데 useEffect()도 실행되면 안될 것 같죠?
맞습니다. 이건 자원낭비입니다.
업데이트될 때는 useEffect() 실행하지 말아주세요
라고도 코드를 짤 수 있습니다.
그러고 싶으면 좋은말 할 때 그대로 따라합니다.
useEffect(()=>{
let 타이머 = setTimeout(()=>{ alert변경(false) }, 2000);
}, []);
useEffect() 함수 끝부분에 대괄호[] 를 집어넣을 수 있습니다.
여기에는 state를 넣을 수 있습니다.
useEffect(()=>{
let 타이머 = setTimeout(()=>{ alert변경(false) }, 2000);
}, [ alert ]);
이런 식입니다. 이렇게 사용하시면
alert라는 이름의 state가 변경이 될 때만 업데이트로 치고 실행해주세요~
라고 명령을 줄 수 있습니다.
일종의 실행조건이라고 생각하시면 되겠습니다.
암튼 그럼 1. Detail컴포넌트 로드가 될 때 & 2. alert라는 state가 변경이 될 때만 실행됩니다.
(대괄호 안에 state는 콤마로 여러개 넣을 수 있습니다)
그럼 이건 무슨뜻일까요?
useEffect(()=>{
let 타이머 = setTimeout(()=>{ alert변경(false) }, 2000);
}, []);
▲ 그냥 []안에 아무것도 안넣었습니다.
조건을 안넣은 겁니다.
그럼 이제 이 useEffect() 코드는 컴포넌트가 업데이트 될 때 절대 실행되지 않습니다.
그냥 컴포넌트 로드때만 한번 딱 실행하고 싶은 코드를 담을 때 쓸 수 있는 일종의 트릭쇼입니다.
암튼 그러면 이제 아까 업데이트 될 때마다 타이머가 동작하는 문제가 해결되었죠?
끝입니다.
setTimeout 타이머를 쓰셨으면 타이머해제도 해야합니다.
방금 Detail 방문시 2초 후에 UI 사라지게 해주세요~ 라고 코드를 짰습니다.
근데 2초가 되기도 전에 Detail을 벗어나면 어떻게 될까요?
지금은 별 문제없는 것 같지만 코드가 길어지거나 꼬이면
남아있는 타이머 때문에 이상한 현상이 일어날 수 있습니다.
그래서 컴포넌트가 사라질 때 타이머를 없애는 코드도 추가해주는게 좋습니다.
useEffect(()=>{
let 타이머 = setTimeout(()=>{ alert변경(false) }, 2000);
return ()=>{ clearTimeout(타이머) }
}, []);
useEffect안에는 return + 함수를 추가하면
컴포넌트가 사라질 때 특정 코드를 실행할 수 있다고 했습니다.
거기에 clearTimeout을 추가한겁니다.
clearTimeout(타이머이름)
이렇게 쓰시면 타이머를 바로 해제할 수 있습니다.
이것이 버그를 예방하는 에프킬라식 코딩입니다.
숙제 완료~~
react에서 중요한 useEffect를 배우면서 useEffect(()=>{},[]) return ()=>{}
양식은 이렇게 되는데 헷갈렸던 부분이 파라터의 두번째 값으로 오는 dependecy array를 비워 놓으면 렌더링이 될때마다 실행이 되어서, return문 다음에 오는 부분은 unmount가 될때 실행 되는거 라고 하였어서 리랜더링이 될때 return 다음에 오는 코드는 실행이 안되어야 하는데 계속 실행이 되는 부분이였다. 내가 이해한 바로는 컴포넌트의 생명주기에서 return 부분이 언마운트 부분으로 넘어 가야하는데 unmount가 되기 전에 props 값이 변경되어 리렌더링을 시켰을때는 return으로 넘어가지 않고 리렌더링 될때 리턴 뒷부분이 계속 실행이되는 것이다. 완벽하게 숙지는 못했지만 더 공부를 해나아 가야겠다.. 일단 내가 원하는 바로 사용할때는 useEffect(()=>{},[]) return ()=>{} , 이런식으로 dependency array에 빈 배열을 넣어서 처음에 랜더링 될때만 실행 할 수 있도록 설정을 맞추놓고 실행을 하자.
이 부분은 js에서 다르게 dom 객체를 찾아서 style 코드에 display를 건드는 방식이 처럼 하지 않고, react에서는 if문도 3항 연산자만 사용이 가능하고 state를 사용 하기 때문에 위에 처럼 UI의 상태를 보이고 안보는 변수를 state로 저장을 한다 (true/false)로 나는 (true)로 처음 상태를 지정, setState[state의 2번째 인자] 부분을 false 로 바꾸도록 코드를
js코드 선언 후에
{
// state가 true일때만 UI를 보이도록 if문 짜기
ex) inputValue == true ?
이렇게 되면 false로 state가 변경 될 시에 null 값이 된다.
UI 나타내고 사라지는 법은 다 이런식으로 사용된다고 하니 기억 해두자.