컴포넌트에게는 생명주기가 있다
- 생성이 될 수도 있고 (mount)
- 재렌더링이 될 수도 있고 (update)
- 삭제가 될 수도 있다. (unmount)
이 원리를 통해 컴포넌트가 장착될때, 업데이트될 때 특정 코드를 실행시킬 수 있다
(=컴포넌트 간섭)
컴포넌트 간섭을 위해 갈고리를 다는 것을 hook 이라고 한다
class Detail2 extends React.Component {
componentDidMount(){
//Detail2 컴포넌트가 로드되고나서 실행할 코드
}
componentDidUpdate(){
//Detail2 컴포넌트가 업데이트 되고나서 실행할 코드
}
componentWillUnmount(){
//Detail2 컴포넌트가 삭제되기전에 실행할 코드
}
}
import {useState, useEffect} from 'react';
function Detail(){
useEffect(()=>{
//여기적은 코드는 컴포넌트 로드 & 업데이트 마다 실행됨
console.log('안녕')
});
let [count, setCount] = useState(0)
return (
<button onClick={()=>{ setCount(count+1) }}>버튼</button>
)
}
상단에서 useEffect import해오고
콜백함수 추가해서 안에 코드 적으면 이제 그 코드는 컴포넌트가 mount & update시 실행된다
위 코드를 통해 Detail 페이지 로드시 콘솔창에 '안녕' 출력이 된다
index.js에 <React.StrictMode>
라는 태그가 있으면 2번 출력해준다
디버깅용으로 편하라고 2번 출력해주는데 싫으면 저 태그를 제거하면 된다
useEffect 안에 적은 코드는 html 렌더링 이후에 동작한다
굉장히 시간이 오래걸리는 코드같은 경우는 useEffect가 뭔가 유용하게 사용될 것이다!
이 원리를 이용하여 useEffect를 사용하면 된다
Detail 페이지에서 "2초 이내 구매 시 할인" 알람창을 2초간 띄워보겠다
우선 UI를 만들어주고
useEffect에서 setTimeout 함수를 사용하였다
그리고 setTimeout 함수 내에서 2초 뒤 display:none
속성을 추가하는 방식으로 구현하였다
export function Detail({data}){
useEffect(()=>{
setTimeout(()=>{
document.querySelector('.alert').style.display='none'
},2000)
})
return(
<>
<div className="alert alert-warning">2초 이내 구매시 할인</div>
...
상세페이지 접속하자마자 알람창이 뜨고 2초 후 사라지며 정상작동이 된다!
내가 구현한 방식은 DOM 요소를 직접 조작하는 방식이다
하지만 이런 방식은 React의 선언적 패러다임에 위배된다.
React는 UI의 상태(state)를 자바스크립트로 선언하고, 그 상태에 따라 UI가 어떻게 보일지를 정의하는 것을 권장한다
➡ React에서 상태를 사용하여 컴포넌트를 보여주거나 숨기는 방식으로 구현해야한다
- UI 상태를 저장할 state 만들고
- state에 따라서 UI가 어떻게 보일지 작성
우선 show state를 만들어서 2초 뒤의 show 상태를 다르게 만들었다
그리고 &연산자를 이용하여 show=true
일때 알람창의 UI를 보여주었다 !
export function Detail({data}){
let [show,setShow]=useState(true)
useEffect(()=>{
setTimeout(()=>{
setShow(false)
},2000)
})
return(
<>
{show && <div className="alert alert-warning">2초 이내 구매시 할인</div>}
...
위의 useEffect는 mount
, update
될 때마다 안의 코드가 실행된다
약간 비효율 적일 수 있기 때문에 mount 될 때만 알람창을 띄우는 것이 좋다
useEffect()의 둘째 파라미터로 [ ]
를 넣을 수 있는데 이곳에 변수나 state같은 것들을 넣을 수 있다
➡ [ ]에 있는 변수나 state 가 변할 때만 useEffect 안의 코드를 실행해준다
useEffect(()=>{ 실행할코드 }, [ state ])
반면, 아무것도 넣지 않으면 mount 시(로드 시) 1회 실행하고 영영 실행해주지 않는다
useEffect(()=>{ 실행할코드 }, [ ])
clean up function 사용
useEffect 내의 return 문이다
useEffect 실행전 & 컴포넌트 unmount 시 실행
useEffect(()=>{
그 다음 실행됨
return ()=>{
여기있는게 먼저실행됨
}
}, [count])
그럼 useEffect 안에 있는 코드를 실행하기 전에 return ()=>{ }
안에 있는 코드를 실행해줍니다
clean up function 사용하는 이유
타이머, 서버 요청 등은 여러 번 실행하면 버그가 생길 수 있기 때문에 한번 동작하면 다시 동작 전 청소해주고 다시 동작시켜야 한다
ex ) 타이머제거, socket 연결요청제거, ajax요청
useEffect(()=>{ 실행할코드 })
useEffect(()=>{ 실행할코드 }, [])
useEffect(()=>{
return ()=>{
실행할코드
}
})
useEffect(()=>{
return ()=>{
실행할코드
}
}, [])
useEffect(()=>{
실행할코드
}, [state1])