React강의 -1

수민·2022년 12월 6일
0

리액트

목록 보기
1/8

🍔컴포넌트 Lifecycle 이란?

컴포넌트도 생명 주기라는 것이 존재한다.

에 접속하면 직관적으로 컴포넌트의 생명주기에 대해 이해할 수있다.

예를 들어서 쇼핑몰 페이지에 접속해서 제품에 대한 상세 설명 페이지를 접속한다고 가정 했을때,

  1. 상세 설명을 담은 컴포넌트가 등장하고 (componentDidMount)
    2.state나 props 를 조작할때 재렌더링되고 (componentDidUpdate)
    3.컴포넌트에서 벗어날때 (componentWillUnmount)

이러한 과정들을 갖는 생명주기를 갖는다.

❓ 그렇다면 컴포넌트의 Lifecycle이 왜 중요한가 ❓

컴포넌트의 이러한 생명주기들을 잘 파악하고 있다면, 컴포넌트의 생명주기 사이사이에 간섭을 해줄수 있다.

  1. 컴포넌트가 등장하기 전에 실행 될 함수
  2. 컴포넌트가 업데이트 될때 실행 될 함수
  3. 컴포넌트가 사라지기전에 실행 될 함수
    등을 작성해줌으로써 컴포넌트들을 렌더링 될때 동시에 특정 작업을 할 수 있다. (갈고리를 걸어놓는다)

❗️ 이럴때 사용하는것이 useEffect() 라는 Hook 이다 ❗️

useEffect() 란 ?

은 글에 작성 되어 있듯이 함수형 컴포넌트에서 클래스형 컴포넌트의 기능들을 사용할 수 있는 것이다.

useEffect는 함수형 컴포넌트에서 컴포넌트의 생명주기에 간섭할수 있도록 하게 해주는 Hook이다.


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

  
  
  
  // useEffect()를 사용하는 법 

import {useState, useEffect} from 'react';

function Detail(){

useEffect(()=>{
  //여기적은 코드는 컴포넌트 mount, update 될때 마다 실행됨
  console.log('안녕')
});

}

❓ 근데 왜 안녕이 2번이나 출력이 될까 ❓

원래 리액트 상에서 디버깅용으로 useEffect 안에 있는 코드는 2번이 실행 된다.

실제로 사이트상에서 발행을 할때는 1번 동작하고, 저기 console 창에서만 임의적으로 2번이 실행 되는 것이다. (신경 쓸 필요 없음!)

1번만 출력되게 하려면 index.js 를 가서 React.strictMode 를 제거해주어야한다.

🔍업데이트(재렌더링) 될때 useEffect() 사용

	useEffect(() => {
    console.log('안녕');
  	})
  let [count, setCount] = useState(0)
  
  
  {count}
  <button onClick={() => setCount(count+1)}>버튼</button>

❗️ 하지만 저 console.log('안녕'); 은 useEffect 바깥에서 작성을 해도 위와 똑같이 출력된다. 왜일까? ❗️

❗️

📌 useEffect() 안에 있는 코드는 HTML이 모두 렌더링 된 후에 실행이 된다.

예를 들어서 반복문을 돌려서 1부터 10000까지 출력하는 코드가 있다고 가정해보자

  useEffect(() => {
    for(let i =0; i <= 10000; i++){
      console.log(i);
    }
  })

  • 이렇게 코드를 작성하면 일단 HTML 을 렌더링 한 후에 저 반복문을 실행시켜주기 때문에, HTML 의 렌더링 속도를 높일수 있다.

  • HTML 이 렌더링 될때마다 동작하는 특정 작업을 Side Effect라고하는데, useEffect라는것도 그에 맞게 작명을 해서 렌더링 될때 처리되어야할 작업들을 비동기로 처리해주는 것이다.

  • 컴포넌트의 핵심 기능은 HTML 렌더링이기 때문에, 그거 외에 다른 기능들을 useEffect 안에 넣어주면 HTML 렌더링 속도를 향상시킬 수 있다. (타이머, 반복연산, 서버에서 데이터가져오기 등등)

🔍 2초 후에 div창 사라지게 하기

let [alert, setAlert] = useState(true);

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

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

alert 와 setAlert 라는 state를 설정하고 alert가 true라면 저 div창을 띄운다.

그후에 useEffect()를 사용해서 2초후에 false로 바뀌게 하면서 그 창을 없애도록 하였다.

🔍 useEffect()의 두번째 인자 [ ]의 의미

📌 useEffect의 형태는 원래 useEffect(callback, dependencyArray) 이다.

📌 그리고 useEffect는 기본적으로 매 렌더링마다 실행된다. 만약에 dependency가 없었다면 컴포넌트가 마운트되고, 업데이트될때마다 useEffect()가 실행 됐을 것이다.

위의 저 코드에서 사실 useEffect() 에서 두번째 인자로 [] 를 넣어주어야한다.

❗️ 저 [ ] 안에는 state나 변수가 들어갈 수 있는데, 의미는 변수나 state의 값이 바뀔때만 저 useEffect를 실행한다는 의미이다 ❗️

let [count, setCount] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      console.log('Hi');
    }, 1000);
  }, [count]);

{count}

<button onClick={() => setCount(count + 1)}>버튼</button>

버튼을 눌러서 저 count state를 변경할때마다 콘솔창을 띄우도록 해보았다.

버튼을 누를때마다 useEffect 안에 있는 콘솔창이 실행되는것을 확인 할 수있다.

만약에 dependency가 없다면 마운트되거나 업데이트 될때마다 실행되지만, dependency를 넣어주면

마운트시 1회만 useEffect 안의 내용들을 실행하고 그 후에는 실행해주지 않는다.

  useEffect(() => {
    setTimeout(() => {
      setAlert(false);
      console.log('Hi');
    }, 1000);
  }, []);

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

만약에 위처럼 일정시간이 지나면 div를 숨기는 useEffect를 실행한다고 했을때, 만약에 []가 없었다면 마운트 될때마다 실행이 되겠지만, [] 를 추가해줌으로써 마운트시에 1회만 실행되도록 한다.


## 🔍 useEffect()의 return
 useEffect(() => {
    setTimeout(() => {
      setAlert(false);
      console.log('Hi');
    }, 1000);

    return () => {
     	 console.log('안녕하세요');
    }
  }, []);

❗️ useEffect에서 return 의 의미는 저 useEffect가 실행되기 전에 return 안에 있는 함수를 실행시켜달라 라는 의미이다 ❗️

렌더링해보면 return문 안에 있는 안녕하세요가 먼저 나온후 그 후에 Hi 가 출력이 되는 것을 확인할 수 있다.

❓ 왜 return문이 필요할까 ❓

이 useEffect가 실행되기전에 먼저 실행되는 return문을 Clean up function 이라고 하는데, 예를 들어서 위의 코드의 useEffect안에 dependency를 작성하지 않았다고 가정해보자. 그렇다면 렌더링 될때마다 setTimeout 함수가 실행될텐데 나중가면 타이머가 여러개 생겨서 버그를 일으킬 수 있다. 이럴때 Clean up function 을 사용해서 타이머 함수를 사용하기 전에 기존 타이머들을 다 제거해줄수가 있다.

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

}, [])
만약 위의 코드라면 기존에 있던 타이머함수 a를 지우고 그 후에 타이머함수를 새로 실행시켜준다는 의미이다.

Clean up function은 타이머함수제거, socket 연결 요청 제거, ajax 요청 중단 등 에 사용된다.

또한 컴포넌트를 언마운트(컴포넌트를 벗어날때) 할때도 Clean up function이 실행 된다.

useEffect

useEffect 쓰는이유

안에있는 코드는 html렌더링 후에 동작합니다.


  for (let i = 0; i < 10000; i++) {
    console.log(i);
  }




  useEffect(() => {
    for (let i = 0; i < 10000; i++) {
      console.log(i);
    }
  });


빠르게 렌더링돼서 보여준다!

안에적는코드

서버에서 데아터가져오는작업, 타이머작업,어려운 연산

왜이름이 side Effect일까?

  • 함수의 핵심기능과 상관없는 부가기능

빡통식 정리


  useEffect(()=>{}) // 재렌더링 코드실행하고 싶으면
  useEffect(()=>{}) // mount시 1회 코드실행하고 싶으면.
 useEffect(()=>{   //unmount시 1회 코드실행하고 싶으면
    return()=>{

    }
  },[])


 useEffect(()=>{},[count]) // 특정 state변경시에만 실행하려면


//
<input> 하나 만들고 거기에 유저가 숫자 말고 다른걸 입력하면

"그러지마세요"라는 안내메세지를 출력해봅시다.


let [num, setNum] = useState("");


  useEffect(() => {
    if (isNaN(num) == true) {
      alert("그러지마세요");
    }
  }, [num]);

   <input onChange={e => setInput(e.target.value)}></input>




참조블로그:https://velog.io/@brgndy/%EB%A6%AC%EC%95%A1%ED%8A%B8-Lifecycle%EA%B3%BC-useEffect-%EC%A0%95%EB%A6%AC

profile
헬창목표

0개의 댓글