본문 바로가기
React

🍏 React Hook

by frontChoi 2025. 10. 24.
반응형

🍇 useState

useState훅은 지역컴퍼넌트에서 데이터를 사용하기 위한 react hook이다

값이 변경될때마다, 리렌더링이 되는 특성이 있다.

 

예시

import { useState } from "react";

type UserType = {
  name: string;
  age: number;
};
export default function State() {
  // 1. useState 사용할 객체 선언
  const [user, setUser] = useState<UserType>({
    name: "",
    age: 0,
  });

  const onClickChangeName = () => {
    // 객체 값 변경
    setUser((prev) => {
      return {
        ...prev,
        name: "최아무개",
      };
    });
  };
  const onClickChangeAge = () => {
    setUser({ ...user, age: 33 });
  };
  return (
    <div className="container mx-auto">
      <p className="mb-3 text-gray-500 dark:text-gray-400">
        이름 : {user.name}
      </p>
      <p className="mb-3 text-gray-500 dark:text-gray-400">나이 : {user.age}</p>

      <hr />
      <button
        onClick={onClickChangeName}
        className="mt-2 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
      >
        이름 변경
      </button>
      <button
        onClick={onClickChangeAge}
        className="mt-2 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
      >
        나이 변경
      </button>
    </div>
  );
}

 

  1. useState를 통해 데이터 타입을 선언한다(typescript이므로 객체의 타입을 name,age를 갖는 UserType을 선언하였다)
    1.  const [user,setUser] = useState<UserType>({ name:"",age:0})
  2. 화면에 보여주기 위하여 user.name, user.age를 보여준다
  3. 객체의 값 변경을 위하여 button을 누르면 onClickChangeAge, onClickChangeName을 통하여 setUser함수를 호출하여 값을 변경한다

 

🚒 useEffect

useEffect는 React 컴퍼넌트가 렌더링이 된 후에 상태 또는 props가 바뀔때 발생하는 hook

 

보통은 컴퍼넌트의 렌더링 최초 발생 , 렌더링 소멸 할때와  특정 값을 감시할때 사용된다

 

렌더링 최초에 사용되는 경우 

useEffect(() => {
    // 최초 실행
    console.log("최초 렌더링");

    return () => {
      // clean up
      console.log("렌더링 소멸");
    };
  }, []);

첫번째 인자에 함수형태로 넣고, 두번째 인자에 빈배열을 넣는다.

그리고 소멸할때 처리 해야할것이 있다면 return 함수에서 처리한다

 

특정 값 감시

const [user, setUser] = useState<UserType>({
    name: "",
    age: 0,
  });
useEffect(() => {
    console.log("나이값 변경");
  }, [user.age]);
  
  
 const onClickChangeAge = () => {
    setUser({ ...user, age: 33 });
  };

useState를 통해 user를 선언하였고,

onClickChangeAge의 함수에서 setUser를 통해 값을 변경할 경우,

useEffect이 발동하면서, "나이값 변경"이라는 콘솔이 찍히게 된다.

 

🚜 useContext

useContext는 컴퍼넌트들 간의 전역적으로 데이터를 공유하기 위한 hook이다.

보통 컴퍼넌트들간의 props drilling 이 발생할때 사용된다

 

"use client";

import { createContext, useContext, useState } from "react";
type AuthContextType = {
  isLogin: boolean;
  login: (username: string) => void;
  logout: () => void;
};
const AuthContext = createContext<AuthContextType | null>(null);
export default function ContextPage() {
  const [islogin, setIsLogin] = useState(false);
  const loginFunc = (username: string) => {
    console.log(username);
    setIsLogin(true);
  };
  const logoutFunc = () => {
    console.log("logout");
    setIsLogin(false);
  };
  return (
    /** Provider를 통해 값을 공급 */
    <AuthContext.Provider
      value={{ isLogin: islogin, login: loginFunc, logout: logoutFunc }}
    >
      <Child />
    </AuthContext.Provider>
  );
}

function Child() {
  /** 자식 컴퍼넌트에서 useContext를 통해 값을 사용 */
  const contextValue = useContext(AuthContext);
  return (
    <>
      <p>{contextValue?.isLogin ? "로그인됨" : "로그인 안됨"}</p>
      <button onClick={() => contextValue?.login("test")}>로그인</button>
      <button onClick={() => contextValue?.logout()}>로그아웃</button>
    </>
  );
}

 

AuthContext는 createContext를 통해 생성되었고, isLogin,login,logout가 필수로 필요하다

AuthContext.Provider를 통해 공급자 역할을 할 수 있다.

Child에서는 useContext를 통해, 전역으로 선언된 value를 사용할 수 있다.

value에는 함수도 전달이 가능하다

 

🚐  useCallBack

함수의 재생성을 방지하기 위해 사용하는 React Hook

 

"use client";

import { useCallback, useEffect, useState } from "react";

type ChildComponentProps = {
  onClickBtn: () => void;
};

function ChildComponent({ onClickBtn }: ChildComponentProps) {
  return (
    <button
      className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
      onClick={onClickBtn}
    >
      버튼1
    </button>
  );
}

export default function CallBack() {
  const [count, setCount] = useState(1);
  console.log("CallBack rendering");

  useEffect(() => {
    console.log("count : ", count);
  }, [count]);
  // Count를 증가시킬때마다, onClickChildComponent가 새롭게 생성되지 않는다.
  const onClickChildComponent = useCallback(() => {
    setCount((prev) => prev + 1);
  }, []);
  return (
    <>
      <div>
        <ChildComponent onClickBtn={onClickChildComponent} />
      </div>
    </>
  );
}

 

onClickChildComponent를 useCallback을 이용하지 않았다면, count가 증가할때마다 계속해서 onClickChildComponent가 새롭게 생성되는 것이 발생할것이다. onClickChildComponent를 사용하면 메모제이션때문에 이전값을 기억하여 새롭게 생성하지 않는다.

(다만 useCallback도 메모리를 사용하는것이기 때문에 속도가 느리지않다면 사용할 이유는 없다)

 

🚐  useMemo

useMemo는 계산된 값을 메모이제이션(기억)해서 불필요한 재계산을 방지하는 Hook입니다.

useCallback은 함수를 기억하는 것이라면, useMemo는 값을 기억하는 것이다

 

"use client";
import { useMemo, useState } from "react";

const cal = (num: number) => {
  console.log("무거운 계산 중...");

  for (let i = 0; i < 1e9; i++) {} // 일부러 느리게
  return num * 2;
};

export default function MemoPage() {
  const [num, setNum] = useState(0);
  // 무거운 계산을 매번 렌더링할때마다, total을 리턴하는것보다는
  // useMemo를 통해서 값이 변경될때마다 하는 것이 효율적이다
  const total = useMemo(() => {
    return cal(num);
  }, [num]);
  return (
    <>
      <p>num : {num}</p>
      <p>total: {total}</p>
      <button
        className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
        onClick={() => setNum((prev) => prev + 1)}
      >
        증가
      </button>
    </>
  );
}

 

useMemo를 사용할 경우 total이 매번 렌더링될때마다 계산되는것이 아닌, num이 변경될때마다 계산되서 리턴하게 된다.

만약 화면이 렌더링이 잦은 경우에는 무거운 계산을 매번렌더링이 아닌, 값이 변경될때마다 하는것이 효율적이다.

 

🚜  useReducer

useReducer는 복잡한 상태 변경 로직을 한 곳에서 관리할 수 있게 해주는 Hook

 

"use client";

import { useReducer } from "react";

type State = {
  name: string;
  email: string;
  password: string;
};

type Action =
  | { type: "CHANGE_INPUT"; field: keyof State; value: string }
  | { type: "RESET" };

const initialState: State = {
  name: "",
  email: "",
  password: "",
};


// 1. reducer에서 state, action 인자 처리 
function reducer(state: State, action: Action) {
  // 2. action에 따라 state 상태 처리 
  switch (action.type) {
    case "CHANGE_INPUT":
      return { ...state, [action.field]: action.value };
    case "RESET":
      return initialState;
    default:
      return state;
  }
}

export default function ReducerPage() {
  // 3.useReducer를 통해 state,dispatch 추출
  const [state, dispatch] = useReducer(reducer, initialState);
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
  };
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    e.preventDefault();
    // 4. 상태 변경에 따라 dispatch를 호출 하고 상태 변경
    dispatch({
      type: "CHANGE_INPUT",
      field: e.target.name as keyof State,
      value: e.target.value,
    });
  };
  return (
    <>
      <form
        onSubmit={handleSubmit}
        className="flex flex-col gap-3 max-w-sm mx-auto p-4"
      >
        <h2 className="text-2xl font-semibold text-center mb-2">회원가입</h2>
        <input
          type="text"
          name="name"
          value={state.name}
          onChange={handleChange}
          placeholder="이름"
          className="border p-2 rounded"
        />
        <input
          type="text"
          name="email"
          value={state.email}
          onChange={handleChange}
          placeholder="이메일"
          className="border p-2 rounded"
        />
        <input
          name="password"
          placeholder="비밀번호"
          type="password"
          value={state.password}
          onChange={handleChange}
          className="border p-2 rounded"
        />

        <button
          type="submit"
          className="bg-blue-500 text-white rounded p-2 hover:bg-blue-600"
        >
          가입하기
        </button>
      </form>
    </>
  );
}

 

useReducer를 이용하면, 사용자의 입력 폼 같은 상황이 발생했을때,

이름,메일,비밀번호를 묶어서 관리 할 수 있다. key값에 대한 변경 reset 등등 한곳에서 관리가 용이하다

 

 

반응형

'React' 카테고리의 다른 글

⚽️Zustand  (0) 2025.12.01

댓글