State Lifecycle

sohyeon kim·2022년 3월 30일
0

React & Javascript

목록 보기
24/41

State 생명주기 (State Lifecycle)

리액트 컴포넌트에는 생명주기(Life Cycle)가 존재한다. 이는 컴포넌트가 브라우저에 나타나고 업데이트 되고, 사라지게 될 떄 호출되는 메서드다.

즉 특정 시점에 코드가 실행되도록 설정할 수 있다는 것이다.


라이프 사이클 함수종류

컴포넌트 라이프 사이클은 크게
Mount , Update , UnMount 3가지로 분류된다.

  1. Mount : Dom 객체가 생성되고 브라우저에 나타나는 것을 의미한다.

  2. Update: 컴포넌트가 업데이트 될 때 실행되는 함수들을 보면 컴포넌트가 업데이트되는 경우는 props 값 변경, state 값 변경, 부모 컴포넌트가 리렌더링 될 때, this.forceUpdate로 강제로 리렌더링 되는 경우가 있다.

  3. UnMount: 컴포넌트가 DOM에서 제거되는 것을 언마운트(UnMount)라고 한다. 호출되는 함수는 하나로 componentWillUnmount 함수이다. 해당 컴포넌트가 제거되기 직전에 호출된다.

메서드를 간략히 나열하자면

  • 그리기: render
  • 그리고 난 뒤: componentDidMount
  • 그리고 난 뒤 변경: componentDidUpdate
  • 그리고 난 뒤 사라짐: componentWillUnmount

did가 붙은 함수는 어떤 작업을 처리한 후에 호출되는 함수이고, will 이 붙틑 함수는 어떤 작업을 처리하기 직전에 호출되는 함수인 것이다.


함수형 컴포넌트의 생명주기 훅 useEffect

클래스 컴포넌트에서만 사용 가능했던 componentDidMout와 같은 생명주기 메서드들이 함수형 컴포넌트에서는 useEffect를 통해 함수형 컴포넌트의 라이프 사이클을 관리할 수 있다.

useEffect는 기본적으로
componentDidMount, componentDidUpdate, componentWillUnmount, getDerivedStateFromProps 의 역할을 모두 수행한다.


componentDidMount

// 의존성 배열[]에 아무것도 넣지 않으면 Mount시에만 렌더해주고 끝난다. (1번만 실행)
useEffect (() =>{
	console.log("마운트 됨");
}, [])

componentDidUpdate와 비슷

// 의존성 배열이 없기 때문에 뭐 하나라도 바뀌면 무조건 다시 실행된다.
useEffect(()=>{
		console.log("수정하고 다시 그려짐")
	})

// someState가 수정될때만 리렌더 해주기
useEffect(()=>{
		console.log("수정하고 다시 그려짐")
	},[someState])

componentWillUnmount

useEffect(()=>{
		console.log("수정하고 다시 그려짐")

		//이부분이 끝나고 진행할 것들
		return()=>{
			console.log("여기서 나가기")
		}
	},[])

componentDidUpdate와 비슷하지만 다른점 하나는, Mount 되자마자 실행되는 점이다.

useEffect의 실행 시점

생명주기 메서드,훅 은 기본적으로 렌더(화면그리기) 이후에 실행된다.
따라서 useEffect와 lifecycle 메서드는 렌더 이후에 실행된다.


전체예제

// 함수형 컴포넌트 useEffect 사용해서 생명주기 !!!
// 생명주기 메서드, 훅은 기본적으로 화면이 render 된 후에 실행횐다.

import { useRouter } from "next/router";
import { useState, useEffect, useRef } from "react";
// useRef 사용해서 input 태그 선택하고, focus() 기능 활용하여 커서를 깜빡이도록 한다.

interface IState {
  count: number;
}
export default function CounterPage() {
  const router = useRouter();

  // inputRef = createRef<HTMLInputElement>();
  const inputRef = useRef<HTMLInputElement>(null);

  const [count, setCount] = useState(99);

  /* 📌 1. DidMount */
  // 1)
  // componentDidMount() {
  //   console.log("마운트됨!!!");
  //   this.inputRef.current?.focus();
  //  포커스 깜빡깜빡
  // }

  // 2)
  // useEffect(() => {
  //   console.log("마운트됨!!!");
  //   inputRef.current?.focus();
  // }, []);
  // 의존성 배열[]에 아무것도 넣지 않으면 Mount시에만 렌더해주고 끝나게 됨

  /* 📌 2. DidUpdate */
  // 1) 
  // componentDidUpdate() {
  //   console.log("수정되고 다시그려짐!!!");
  // }

  // 2)
  // useEffect(() => {
  //   console.log("수정되고 다시그려짐!!!");
  // });
  // 의존성 배열이 없기 때문에 뭐 하나라도 바뀌면 무조건 다시 실행

  useEffect(() => {
    console.log("수정되고 다시그려짐!!!");
  }, [count]);
  // count가 수정될때만 리렌더

  /* 📌 3. WillUnmount */
  // 1)
  // componentWillUnmount() {
  //   console.log("컴포넌트 사라짐!!!");
  //   // 채팅방 나가기
  //   // api 요청!!!
  // }

  // 2)
  // useEffect(() => {
  //   return () => {
  //     console.log("컴포넌트 사라짐!!!");
  //   };
  // }, []);

  /* 📌 4. DidMount와 WillUnmount를 합치기!! */
  useEffect(() => {
    console.log("마운트됨!!!");
    inputRef.current?.focus();

    return () => {
      // 나갈때
      console.log("컴포넌트 사라짐!!!");
    };
  }, []);

  /* 📌 5. useEffect의 잘못된 사용 예(1. 추가렌더링, 2. 무한루프) */
  // useEffect(() => {
  //   setCount((prev) => prev + 1);
  // }, [count]);

  const onClickCounter = () => {
    // console.log(this);
    // console.log("카운터 클릭!!!");
    // console.log(this.state.count);
    // this.setState((prev: IState) => ({
    //   count: prev.count + 1,
    // }));
    setCount((prev) => prev + 1);
  };

  const onClickMove = () => {
    router.push("/");
  };

  console.log("나는 언제 실행되게?!!");

  return (
    <div>
      <input type="text" ref={inputRef} />
      <div>현재카운트: {count}</div>
      <button onClick={onClickCounter}>카운트 올리기!!!</button>
      <button onClick={onClickMove}>나가기!!!</button>
    </div>
  );
}


useEffect 안에서 setState 사용시 주의 사항

useEffecrt 내에서 setState를 사용할때는 정말 필요한 경우가 아니라면 지양하기.

컴포넌트가 마운트돈 이후 setState 를 적용하게 되면
state가 변경되고, 변경된 state로 컴포넌트가 다시 그려지게 된다.

여기서 useEffect 내에서 setState 를 사용학 되면 불필요한 리렌더나 무한루프를 일으키게 되고 성능면에서도 비효율적이다.

profile
slow but sure

0개의 댓글