본문 바로가기
Express, Next.js/Next.js, React

[React] useState, useEffect, useRef 정리

by 방배킹 2024. 4. 19.

Component

React 애플리케이션을 구성하는 블록

컴포넌트는 상태(state)를 가질 수도 있고, 속성(props)을 통해 데이터를 받아와서 렌더링할 수 있다.

state

"State(상태)"는 React 컴포넌트 내부에서 관리되는 데이터이다.

각 컴포넌트는 자체적으로 상태를 가질 수 있으며, 상태가 변경될 때마다 React는 해당 컴포넌트를 다시 렌더링하여 UI를 업데이트한다.

props

리액트에서는 하나의 컴포넌트에서 다른 컴포넌트에게 데이터를 전달할 때 props를 사용한다. (부모컴포넌트가 자식 컴포넌트에게)

props는 다른 컴포넌트에 데이터를 전달하기 위한 메커니즘, 시스템이다.

 

// 자식 컴포넌트에게 props를 전달하는 방법
export default function Profile() {
  return (
    <Avatar
      person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
      size={100}
    />
  );
}

//자식 컴포넌트가 porps를 받는 방법
function Avatar({ person, size }) {
  // person과 size는 이곳에서 사용가능합니다.
}

 

 

 

useState

컴포넌트에서 상태를 사용하려면 useState를 통해 상태를 선언하고 사용하면된다.

 

const [age, setAge] = useState(42);

 

useState(42) 를 통해  age라는 상태를 선언하고 초기값은 42로 설정해주었다.

setAge(age+1);

 

setAge() 메서드를 통해 상태값을 변경해줄 수 있다.

 

useEffect

useEffect는 총 3가지로 나누어 진다. (setup code, cleanup code, dependencies)

 

setup code는 컴포넌트가 랜더링 될때마다 실행된다. 이때 dependencies가 존재하면 해당 배열에 들어있는 값이 변경될때만 setup code가 실행된다.

useEffect(() => {
  	// setup code
  }, []);

 

만약 dependencies에 빈배열을 전달하면 컴포넌트가 맨 처음 랜더링 될때만 실행된다.

 

이후 dependencies에 있는 내용이 변경되면 cleanup code 가 변경되기 전 props와 state 값으로 실행이되고.

setup code가 변경된 새로운 props와  state 값으로 실행이 된다.

 

cleanup code는 어떤 역할을 하는것일까?

 

아래와 같은 코드가 있다고 해보자.

import React, {useEffect} from 'react'

function Timer(props){
	useEffect(()=>{
    	const timer = setInterval(()=>{
        	console.log("타이머 실행중");
        },1000);
    });
    
    return(
    	<div>
        	<span>타이머를 시작합니다</span>
        </div>
    )
}
export default Timer;

 

import React, {useState} from 'react'
import Timer from './Timer'


function App() {
  const [showTimer, setShowTimer] = useState(false);
  return (
    <div className="App">
      {showTimer && <Timer />}
      <button onClick={()=>setShowTimer(!showTimer)}>Toggle Timer</button>
    </div>
  );
}
export default App;

 

버튼을 누르면 Timer 컴포넌트가 생기고 랜더링 되면서 console에 "타이머 실행중" 이 출력된다.

 

 

 

버튼을 다시 눌러 state 값을 false로 변경하면 언마운트 되면서 컴포넌트는 보이지 않지만 console에는 "타이머 실행중" 이 계속 출력된다.

setInteval로 생성한 타이머를 제거 하지 않았기 떄문이다. clean up 코드를 통해 해결할 수 있다.

 

 

Timer 컴포넌트에 clean up 코드를 추가해주자

import React, {useEffect} from 'react'

function Timer(props){
	useEffect(()=>{
    	const timer = setInterval(()=>{
        	console.log("타이머 실행중");
        },1000);

        return function cleanUp(){
            clearInterval(timer);
            console.log("타이머 종료");
        }
    });
    
    return(
    	<div>
        	<span>타이머를 시작합니다</span>
        </div>
    )
}

export default Timer;

 

 

버튼을 다시 누르면 언마운트 되면서 clean up 함수가 실행되고 타이머가 종료 되는것을 확인 할 수 있다.

 

 

useRef

 

useRef는 ref 객체를 반환한다.

const ref = useRef("test"); // {current:"test"}

const ref = useRef("hello"); // {current:"hello"}

 

 

 

ref 값을 변경하는것을 state와 다르게 컴포난트를 다시 랜더링 하지 않는다.

즉, ref는 컴포넌트의 보여지는 부분이 아닌 정보를 저장하는데 어울린다.

 

import React, {useState,useRef} from 'react'

function App() {
  const [count, setCount] = useState(0);
  const countRef = useRef(0);

  console.log("state: ",count);
  console.log("countRef: ",countRef);
  return (
    <div className="App">
      <p>State: {count}</p>
      <p>Ref: {countRef.current}</p>
      <button onClick={()=>setCount(count+1)}>state 증가</button>
      <button onClick={()=>countRef.current=countRef.current+1}>state 증가</button>
    </div>
  );
}

export default App;

 

 

state 증가 버튼을 누르면 state 값이 변경되고 랜더링이 되어 변경사항이 적용된다.

 

 

ref 증가 버튼은 눌러도 랜더링이 되지 않기 때문에 console에는 값이 증가하지만 페이지에는 변화가 없다.

 

이때 state 증가 버튼을 눌러 state 값을 증가시켜 페이지를 다시 랜더링 하면 변화된 ref 값이 페이지에 보인다.

 

 

댓글