본문 바로가기
JavaScript/React

React) Hooks - useState, useEffect

by 박채니 2022. 11. 15.
안녕하세요, 코린이의 코딩 학습기 채니 입니다.
[리액트를 다루는 기술]의 책을 참고하여 포스팅한 개인 공부 내용입니다.

 

Hooks - useState, useEffect

 

useState

- 가장 기본적인 Hook

- 함수 컴포넌트에서도 가변적인 상태를 지닐 수 있게 해줌

- 상태 관리 시 사용

 

Counter.js

import { useState } from 'react';

const Counter = () => {
    const [ value, setValue ] = useState(0);

    return(
        <div>
            <p>현재 카운터 값은 <b>{value}</b>입니다.</p>
            <button onClick={() => setValue(value + 1)}>+1</button>
            <button onClick={() => setValue(value - 1)}>-1</button>
        </div>
    );
};

export default Counter;

useState 함수의 파라미터에 기본 값을 넣어주어 value의 기본 값은 0으로 설정 되어 있습니다.

함수 호출 시 배열을 반환하게 되는데, 배열의 첫 번째 원소상태 값 / 두 번째 원소상태를 설정하는 함수입니다.

해당 함수에 파라미터를 넣어 호출하면, 값이 전달 받은 파라미터로 변경되고 리렌더링 됩니다.

 

App.js

import './App.css';
import Counter from './Counter';

const App = () => {
  return <Counter />
}

export default App;

처음 렌더링 시
+1 클릭 시 (0 기준)
-1 클릭 시 (0 기준)

카운터가 정상적으로 작동하는 것을 확인할 수 있습니다.

 

useState 여러 번 사용하기

 

하나의 useState는 하나의 상태 값만을 관리할 수 있으므로, 관리할 상태가 여러 개라면 useState를 여러 번 사용하면 됩니다.

 

Info.js

import { useState } from "react";

const Info = () => {
    const [ name, setName ] = useState('');
    const [ nickname, setNickname ] = useState('');

    const onChangeName = (e) => {
        setName(e.target.value);
    }

    const onChangeNickname = (e) => {
        setNickname(e.target.value);
    }

    return (
        <div>
            <div>
                <input value={name} onChange={onChangeName}/>
                <input value={nickname} onChange={onChangeNickname} />
            </div>
            <div>
                <div>
                    <b>이름 : </b> {name}
                </div>
                <div>
                    <b>닉네임 : </b> {nickname}
                </div>
            </div>
        </div>
    );
}

export default Info;

 

App.js

import './App.css';
import Info from './Info';

const App = () => {
  return <Info />
}

export default App;

name과 nickname 총 2개의 상태를 2개의 useState로 관리할 수 있는 것을 확인할 수 있습니다.

 


useEffect

- 렌더링될 때마다 특정 작업을 수행하도록 설정

- 클래스형 컴포넌트의 componentDidMount와 componentDidUpdate를 합친 형태

 

Info.js

import { useState, useEffect } from "react";

const Info = () => {
    const [ name, setName ] = useState('');
    const [ nickname, setNickname ] = useState('');

    useEffect(() => {
        console.log('렌더링이 완료되었습니다!');
        console.log({ name, nickname });
    });

    const onChangeName = (e) => {
        setName(e.target.value);
    }

    const onChangeNickname = (e) => {
        setNickname(e.target.value);
    }

    return (
        <div>
            <div>
                <input value={name} onChange={onChangeName}/>
                <input value={nickname} onChange={onChangeNickname} />
            </div>
            <div>
                <div>
                    <b>이름 : </b> {name}
                </div>
                <div>
                    <b>닉네임 : </b> {nickname}
                </div>
            </div>
        </div>
    );
}

export default Info;

처음 렌더링 시
name : a, nickname : b 입력 시 리렌더링

이처럼 렌더링이 완료된 후 작업이 수행된 것을 확인할 수 있습니다.

 

마운트될 때만 실행하고 싶을 때

 

useEffect 내 작업을 맨 처음 렌더링될 때만 실행하고 업데이트될 때는 실행하지 않고 싶다면,

두 번째 파라미터에 빈 배열을 넣어줍니다.

 

Info.js - useEffect

useEffect(() => {
    console.log('마운트될 때만 실행!!');
}, []);

name과 nickname을 입력하여도 (업데이트로 리렌더링 되어도), 콘솔 창에는 '마운트될 때만 실행!!'이 한 번 찍히는 것을 확인할 수 있습니다.

 

특정 값이 업데이트될 때만 실행하고 싶을 때

 

name의 값만 업데이트가 되었을 때만 특정 작업을 수행하고 싶을 땐, 두 번째 파라미터의 배열 안에 검사하고 싶은 값을 넣어줍니다.

 

Info.js - useEffect

useEffect(() => {
    console.log(name);
}, [name]);

nickname을 업데이트 하였을 땐 useEffect 내 특정 작업이 수행되지 않았음을 확인할 수 있습니다.

배열 안에는 useState로 관리하고 있는 상태 혹은 props로 전달 받은 값 등을 사용할 수 있습니다.

 

뒷정리하기

 

useEffect는 렌더링 된 후 특정 작업을 수행하지만,

언마운트 되기 이나 업데이트되기 직전에 특정 작업을 수행하고 싶을 때useEffect에서 뒷정리(cleanup) 함수를 반환해 줍니다.

 

Info.js - useEffect

useEffect(() => {
    console.log('effect - ', name);

    // 뒷정리함수
    return () => {
        console.log('cleanup - ', name);
    }
}, [name]);

 

App.js

import './App.css';
import { useState } from 'react';
import Info from './Info';

const App = () => {
  const [visible, setVisible] = useState(false);

  return (
    <div>
      <button onClick={() => setVisible(!visible)}>{visible ? '숨기기' : '보이기'}</button>
      <hr/>
      {visible && <Info />}
    </div>
  );
}

export default App;

렌더링될 때마다 뒷정리 함수가 나타나고, 업데이트되기 직전의 값을 보여주는 것을 확인할 수 있습니다.

(마찬가지로 언마운트될 때만 뒷정리 함수 호출을 원한다면, 두 번째 파라미터는 [ ]로 선언)