State/Hook/useState/useEffect

Hover·2022년 9월 15일

1. react state

리액트의 핵심 내용인 state에 대해 알아보자.

state는 컴포넌트의 렌더링 결과물에 영향을 주는 데이터를 가지고 있는 객체다.

이것은 props와 유사한데, 가장 큰 차이점은, props는 컴포넌트 내에서 값을 바꿀 수 없었다.

하지만 state는 컴포넌트 내에서 값을 바꿀 수 있다.

컴포넌트에서 동적인 상태를 state라고 부른다.


import React from 'react'

function Statestudy() {
    let myname = "hello"
    const onClickbutton = ()=>{
        myname="hi";
        console.log(myname);
    }
  return (
    <div>
        <button onClick={onClickbutton}>ClickClickClick</button>
        <h3>Name is {myname}</h3>
    </div>
  )
}

export default Statestudy

버튼을 클릭하면 name이 hi로 바뀌는 코드를 작성하였다.

콘솔창에서는 변수가 잘 변한걸 확인할 수 있지만 렌더링은 되지 않는 모습을 볼 수 있다.

이제 이 코드를 useState를 이용해 작성 해보겠다.

2. useState

React Hooks가 나오기 전까진 상태(state)값을 관리하기 위해 클래스 컴포넌트를 작성해야 했다.

클래스 컴포넌트는 일반 함수형 컴포넌트와는 다르게 상당히 복잡하여 유지 보수가 힘들었다.

하지만, Hooks라는 기능이 도입되면서 함수형 컴포넌트에서도 상태를 관리할 수 있게 되었다.

이 Hooks중에 useState라는 함수를 사용할 것이다.

const [var,setVar] = useState("default");

useState를 호출하면 배열을 반환하는데

첫번째 원소는 현재 상태 값 변수이고, 두번째 변수는 상태값을 갱신해주는 setter함수다.

그리고 useState안의 괄호 값은 상태의 초기값이다.

import React,{useState} from 'react'

function Statestudy() {
  const [myname,setMyname] = useState("hello");
    //let myname = "hello"
    const onClickbutton = ()=>{
        setMyname("hi");
        console.log(myname);
    }
  return (
    <div>
        <button onClick={onClickbutton}>ClickClickClick</button>
        <h3>Name is {myname}</h3>
    </div>
  )
}

export default Statestudy

useState를 통해 코드를 재작성 해보았다.

렌더링은 잘 되는 것을 볼 수 있다.

그런데 왜 콘솔에서는 이전 상태값이 나올까?

useState는 비동기적 처리를 하는 함수다. 비동기적 처리는 함수의 결과를 기다리지 않고 그 다음 코드를 실행한다.

function Statestudy() {
  const [numbers,setNumbers] = useState(0);

    const onClickbutton = ()=>{
      setNumbers(numbers+1);
      setNumbers(numbers+1);
      setNumbers(numbers+1);
    }
  return (
    <div>
        <p>{numbers}</p>
        <button onClick={onClickbutton}>PlUS</button>
    </div>
  )
}

비동기적 처리의 예시 코드다.

코드상으로 봤을 땐 버튼 클릭시 setNumbers가 세 번 작동해 숫자가 3씩 증가해야하지만,
직접 눌러보면 1씩 증가하는 것을 볼 수 있다.

setState는 왜 비동기로 동작할까?

하나의 페이지나 컴포넌트 내에 수많은 상태값이 존재한다.

이 상태값 하나하나가 바뀔 때마다 렌더링된다면 성능에 문제가 생길 수 있다.

이 useState를 동기적으로 처리하려면 useEffect를 사용하면 된다.

3.useEffect

useEffect함수는 리액트 컴포넌트가 렌더링 될 때마다 특정 작업을 실행할 수 있도록 하는 Hooks이다.

useEffect함수는 component가 mount/unmount/update 됐을 때 특정 작업을 처리할 수 있다.

useEffect() 사용법

useEffect(()=>{
 console.log("마운트 될 때 실행"); 
},[]);
  • 컴포넌트가 화면에 가장 처음 렌더링 될 때 한 번만 실행하고 싶을 때는 deps위치에 빈 배열을 넣는다.
  • 이 빈 배열은 이펙트에 리액트 데이터흐름에 관여하는 어떠한 값도 사용하지 않겠다는 뜻으로, 한 번 적용되어도 안전하다는 뜻이다.
useEffect(()=>{
 console.log("리렌더링 될 때마다 실행"); 
});
  • 배열을 생략하면 리렌더링 될 때마다 실행된다.
useEffect(()=>{
 console.log(name);
 console.log("특정 요소가 업데이트 될 때 실행")
},[name]);
  • 특정 요소가 업데이트 될때 실행하고 싶으면 배열에 검사하고 싶은 값을 넣어주면 된다.
useEffect(()=>{
 console.log("effetct");
  console.log(name);
  return ()=>{
    console.log("cleanup");
    console.log(name):
  }
},[]);
  • cleanup함수 반환(useEffect내의 return 뒤에 나오는 함수)

위 예제를 코드로 작성해보겠다.

function Statestudy() {
  const [numbers,setNumbers] = useState(0);

    const onClickbutton = ()=>{
      setNumbers(numbers+1);
    }
    useEffect(()=>{
      console.log("Effect-onetime");
    },[]);
    useEffect(()=>{
      console.log("Effect-rerender");
    });
    useEffect(()=>{
      console.log("Effect-plusnum");
      return ()=>{
        console.log("cleanup");
        alert("number is change");
      }
    },[numbers]);
  return (
    <div>
        <p>{numbers}</p>
        <button onClick={onClickbutton}>PlUS</button>
    </div>
  )
}

초기 화면일때 출력되는 콘솔 창이다.

렌더링이되고 plusnum의 값이 정해졌으므로 rerender와 plusnum이 작동한다.


plus버튼을 클릭하면 cleanup함수가 잘 실행이된다.

이후 alert의 확인 버튼을 누르면 렌더링이 시작되며 마찬가지로 두 개의 useEffect 함수를 실행해준다.

참고글 : https://www.rinae.dev/posts/a-complete-guide-to-useeffect-ko

profile
프론트엔드 개발자 지망생입니다

0개의 댓글