본문 바로가기
Front-End/React

[리액트를 다루는 기술] Hooks_1 (useState, useEffect, useReducer)

by Cafe Mocha 2022. 5. 4.

8장 Hooks

8.1 useState

useState는 가장 기본적인 Hook이며, 함수 컴포넌트에서도 가변적인 상태를 지닐 수 있게 해준다.

import React from "react";
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;

8.2 useEffect

useEffect는 리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있는 Hook입니다.

import React, { useEffect } from "react";
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);
  };

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

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

export default Info;
  • useEffect 두번째 파라미터에 따라서 마운트때만, 특정값이 업데이트 될 때만 실행가능하다.
  • 뒷정리하기
    useEffect(() => {
        console.log("effect");
        console.log(name);
        return () => {
          console.log("cleanup");
          console.log(name);
        };
      }, []);
    
  • 컴포넌트가 언마운트 되기 전이나 업데이트되기 직전에 어떤 작업을 수행하고 싶다면 useEffect에 뒷정리 함수를 반환

8.3 useReducer

  • useReducer는 useState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 업데이트해 주고 싶을 때 사용하는 Hook이다.
  • 리듀서는 현재 상태, 그리고 업데이틀ㄹ 위해 필요한 정보를 담은 액션 값을 전달받아 새로운 상태를 반환하는 함수이다. (리듀서 함수에서 새로운 상태를 만들 때는 반드시 불변성을 지켜야 한다.)
function reducer(state,action){
	return {...} //불변성을 지키면서 업데이트한 상태를 반환한다.
}

//액션 값은 주로 다음과 같은 형태로 이루어져 있다.
{
	type : 'INCREMENT'
}

카운터 구현하기

import React from "react";
import { useReducer } from "react";
import { useState } from "react";

function reducer(state, action) {
  switch (action.type) {
    case "INCREMENT":
      return { value: state.value + 1 };
    case "DECREMENT":
      return { value: state.value - 1 };
    default:
      return state;
  }
}

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, { value: 0 });
  return (
    <div>
      <p>
        현재 카운터의 값은 <b>{state.value}</b>입니다.
      </p>
      <button
        onClick={() => {
          dispatch({ type: "INCREMENT" });
        }}
      >
        +1
      </button>
      <button
        onClick={() => {
          dispatch({ type: "DECREMENT" });
        }}
      >
        -1
      </button>
    </div>
  );
};

export default Counter;

여러 개의 state 관리하기

import { useReducer } from "react";

function reducer(state, action) {
  return {
    ...state,
    [action.name]: action.value,
  };
}

const Info = () => {
  const [state, dispatch] = useReducer(reducer, {
    name: "",
    nickname: "",
  });

  const { name, nickname } = state;

  const onChange = (e) => {
    dispatch(e.target);
    console.log(e.target.value);
    console.log(e.target.name);
  };

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

export default Info;