본문 바로가기
> 메모/React

[리액트] Lifecycle / useEffect(훅) / clean up function

by 자몽주스 2024. 5. 27.
728x90
Lifecycle
- 컴포넌트 인생주기
- 컴포넌트 인생 중간중간에 간섭

 

1. 생성 (mount)
2. 재렌더링(update)
3. 삭제 (unmount)

간섭 방법 >>

= 갈고리(훅) 달아서 간섭


갈고리 다는 법
(구버전)
class Detail2 extends React.Component {
  componentDidMount(){
    //Detail2 컴포넌트가 로드되고나서 실행할 코드
  }
  componentDidUpdate(){
    //Detail2 컴포넌트가 업데이트 되고나서 실행할 코드
  }
  componentWillUnmount(){
    //Detail2 컴포넌트가 삭제되기전에 실행할 코드
  }
}

갈고리 다는 법
(요즘 버전)
- useEffect 함수
useEffect 함수 사용 방법 - import 먼저
import { useEffect } from "react";

상단에 import 하기.

  useEffect(() => {});

useEffect 안에 함수 하나 집어넣어서 사용

 

useEffect 안에 적은 코드는

mount / update 시 작동됨을 의미.

 

실은 useEffect 바깥에 적어도 똑같이 컴포넌트 mount & update시 실행

useEffect 안에 적은 코드는 html 렌더링 이후에 동작함.

function Detail(){

  useEffect(()=>{
    (반복문 10억번 돌리는 코드)
  });
  
  return (생략)
}

 useEffect 안에 적으면 html 먼저 보여주고 나서 반복문 돌림 

= return 문 안에 생략된 html 먼저 보여줌. 


useEffect 함수 활용
Detail 페이지 후 2초 후에 박스가 사라지게 하기

 

1. UI 상태를 저장할 state 만들고
2. state에 따라서 UI가 어떻게 보일지 작성
UI를 껐다키는 스위치(리모컨 버튼) 생성
= state 생성하기. 
  useEffect(() => {
    setTimeout(() => {}, 2000);
  });

 

2초 후 박스 사라지게 하기 위한 코드를

useEffect 함수 활용해서 작성.

1. UI 상태를 저장할 state 만들고
= (리모컨 버튼) 생성
  let [alert, setAlert] = useState(true);

현재 UI 상태 state 로 생성.

true 로 껐다 키는 기본값 넣음.

2. 조건문 달기
- 이런 조건 시 팝업창 박스 보여주기

= 삼항연산자를 이용해서 버튼 환경 생성
= 이런 상황일 때 리모컨 버튼 누르기.

 

alert 가 true 일 때 만 팝업창 박스를 보여주는 것

    {alert == true ? (
        <div className="alert alert-warning">2초 이내 구매 시 할인</div>
      ) : null}

중괄호 써서 삼항 연산자 코드 중간에 기입.

true 가 아닐 경우 아무것도 보여주지 않는 null

import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";

///detail 접속시 html 이쁜거 보여달라
function Detail(props) {
  let { id } = useParams();
  // console.log(id);
  let [alert, setAlert] = useState(true);

  // 2초 후 박스 사라짐 - useEffect 활용
  useEffect(() => {
    setTimeout(() => {}, 2000);
  });

  return (
    <div className="container">
      {alert == true ? (
        <div className="alert alert-warning">2초 이내 구매 시 할인</div>
      ) : null}
      <div className="row">
        <div className="col-md-6">
          <img
            src="https://codingapple1.github.io/shop/shoes.jpg"
            width="100%"
          />
        </div>
        <div className="col-md-6">
          <h4 className="pt-5">{props.shoes[id].title}</h4>
          <p>{props.shoes[id].content}</p>
          <p>{props.shoes[id].price}</p>
          <button className="btn btn-danger">주문하기</button>
        </div>
      </div>
    </div>
  );
}

export default Detail;
alert 창은 2초 후에 꺼달라고 코드 짜기. 
- setAlert()
 state 변경함수 사용
  useEffect(() => {
    setTimeout(() => {
      setAlert(false);
    }, 2000);
  });

이렇게 짜면 2초 뒤에 꺼짐.

끝 부분에 [] 추가하기
  // 2초 후 박스 사라짐 - useEffect 활용
  useEffect(() => {
    setTimeout(() => {
      setAlert(false);
    }, 2000);
  }, []);

끝에 [] 추가해주면 더 정확해진다.

저 대괄호에다가 아무런 변수나 state를 넣을 수 있음

변수 안넣고 대괄호만 사용 가능

  // 2초 후 박스 사라짐 - useEffect 활용
  useEffect(() => {
    setTimeout(() => {
      setAlert(false);
    }, 2000);
  }, [count]);

대괄호 넣기 전에는  mount 될 때 실행

- 컴포넌트 장착될 때

1회만 실행하고 싶은 경우

 

대괄호 넣게되면

대괄호 안에 변수(count)가 변할 때마다

기존과 달라질 때마다 

중괄호 안에 있는 코드 실행


[] 의 사용
- useEffect에 넣을 수 있는 실행조건 
useEffect(()=>{ 실행할코드 }, [count])

useEffect()의 둘째 파라미터로 [ ] 를 넣을 수 있음.

대괄호 안에 아무것도 안넣을 경우
useEffect(()=>{ 실행할코드 }, [])

대괄호 안에 아무것도 안넣으면

컴포넌트 mount시 (로드시) 1회 실행하고 영영 실행해주지 않음.

대괄호 안에 변수 넣었을 경우
useEffect(()=>{ 실행할코드 }, [count])

 [ ]에 있는 변수나 state 가 변할 때만 useEffect 안의 코드를 실행

= count라는 변수가 변할 때만 useEffect 안의 코드가 실행


clean up function
- useEffect 동작하기 전에 특정코드를 실행
- return ()=>{} 
리턴 문 추가
- unmount 시 실행
= unmount = 컴포넌트 삭제될 때
( 다른 페이지로 넘어갔을 때 )
  useEffect(() => {
    setTimeout(() => {
      setAlert(false);
    }, 2000);
  }, []);

이 코드에서 

return 문 추가 가능.

  useEffect(() => {
    setTimeout(() => {
      setAlert(false);
    }, 2000);
    return () => { 여기에 코드 작성 가능 };
  }, []);

return 문 추가.

return 문 중괄호 안에 코드 작성 가능

=  useEffect 실행 되기 전에 실행된다.

=  clean up function

clean up function
useEffect(()=>{ 
  그 다음 실행됨 
  return ()=>{
    여기있는게 먼저실행됨
  }
}, [count])

useEffect 안에 썼기 때문에 

컴포넌트가 mount 될 때 마다 실행 될 때 생기는 버그를 방지

useEffect(()=>{ 
  그 다음 실행됨 
  return ()=>{
    기존 타이머 제거해달라
  }
}, [count])

기존 타이머를 싹 제거한 상태에서

꼭 필요한 타이머 하나를 장착할 수 있음.

타이머 제거하는 코드
   setTimeout(() => {
      setAlert(false);
    }, 2000);

이걸 변수에 저장해놓고 쓰기

    let a = setTimeout(() => {
      setAlert(false);
    }, 2000);

변수 a 에 저장

clearTimeout 함수 사용
useEffect(()=>{ 
  let a = setTimeout(()=>{ setAlert(false) }, 2000)
  return ()=>{
    clearTimeout(a)
  }
}, [])

나중에 타이머 제거하도록 코드짜기.


정리
useEffect(()=>{ 실행할코드 })

재렌더링마다 코드를 실행

useEffect 안에 적은 코드는 html 렌더링 이후에 동작

useEffect(()=>{ 실행할코드 }, [])

 컴포넌트 mount시 (로드시) 1회만 실행

useEffect(()=>{ 
  실행할코드
}, [state1])

 state1이 변경될 때만 실행

useEffect(()=>{ 
  return ()=>{
    실행할코드
  }
}, [])

useEffect 실행 전에 실행

useEffect 실행 전에 깔끔하게 싹 비우고 싶은 경우 

728x90