프론트엔드 개발자의 기록 공간

[React] React(7) 본문

프로그래머스 데브코스_FE/TIL

[React] React(7)

[리우] 2022. 1. 26. 16:30

❗❗  데브코스 54일차 (10.14)

오늘도 자주 사용되는 컴포넌트 로직을 함수로 뽑아내는 연습을 진행한다.
프론트 개발을 하다 보면, 프론트에서 자체적으로 저장해야 하는 데이터들이 있다. (임시저장 데이터, 토큰 등) 이를 위해서 localStorage, sessionStorage를 이용하게 된다.

또한, 특정 이벤트가 발생하고 몇 초 뒤에 어떠한 로직을 수행하는 setTimeOut() 함수도 자주 사용된다.
몇 초 뒤 다른 페이지로 이동 등등...
이 두 가지를 Custom Hook으로 만들어보는 과정을 설명하겠다.

✅ useLocalStorage - Custom Hook

import { useState } from "react";

	// localStorage 저장할 key값, 초기값
const useLocalStorage = (key, initialValue) => {
  const [storedValue, setStoredValue] = useState(() => {
  // localStorage에 key값에 해당하는 값이 존재하면 가져오고 아니면 초기값으로 저장
    try {
      const item = localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

	// localStorage에 저장
  const setValue = (value) => {
    try {
    // value가 함수이면 함수 결과값 저장
      const valueToStore =
        typeof value === "function" ? value(storedValue) : value;

      setStoredValue(valueToStore);
      // localStorage는 문자열로 저장되므로 객체를 저장할 때는, stringify로 변환해줘야한다.
      localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(error);
    }
  };

  return [storedValue, setValue];
};

export default useLocalStorage;

📚 useLocalStorage - StoryBook 코드

import useLocalStorage from "../../hooks/useLocalStorage";

export default {
  title: "Hook/useLocalStorage",
};

export const Default = () => {
  const [status, setStatus] = useLocalStorage("status", "404 NOT FOUND");

  return (
    <div>
      <button onClick={() => setStatus("200 OK")}>Resend</button>
      {status}
    </div>
  );
};

useLocalStorage에 key 값을 "status", 초깃값 "404 NOT FOUND" 설정
이후 버튼 클릭 시 setStatus(setValue)를 통해 "200 OK"로 저장
useSessionStorage도 위의 코드와 동일하다. localStorage를 sessionStorage로 바꿔주면 된다.
(사용법이 같기 때문에)

 

✅ useTimeOut - Custom Hook

TimeOut에는 두 가지 방법이 존재한다.

1. 함수 호출을 통한 방법

2. 컴포넌트가 로딩 된 후 바로 실행되는 방법

두 가지를 소개하겠다.

 

✍ 1. 함수 호출을 통한 방법 (useTimeOutFn)

import { useCallback, useEffect, useRef } from "react";
		// props 실행할 함수, 몇 초 뒤 실행할지
const useTimeoutFn = (fn, ms) => {
  // timeOut에 대한 Id를 기억할 변수
  const timeoutId = useRef();
  // 함수도 Ref를 통해 최적화
  const callback = useRef(fn);
  
  useEffect(() => {
    // 마운트시 ref를 통해 함수 기억 
    callback.current = fn;
  }, [fn]);
  
  // 지정한 timeOut이 끝나면 함수 실행
  const run = useCallback(() => {
    // 이전에 등록한 timeOutId가 남아있다면 clear로 해제를 해준다.
    timeoutId.current && clearTimeout(timeoutId.current);
    
    // timeOut을 세팅하고 timeOut이 끝나면 fn함수를 실행 시킨다
    timeoutId.current = setTimeout(() => {
      callback.current();
    }, ms);
  }, [ms]);

  // 함수 종료
  const clear = useCallback(() => {
    // timeOutId가 있다면 clear로 해제를 해준다.
    timeoutId.current && clearTimeout(timeoutId.current);
  }, []);

  // clean-up
  useEffect(() => clear, [clear]);

  return [run, clear];
};

export default useTimeoutFn;

📚 useTimeOutFn - StoryBook 코드

import useTimeoutFn from "../../hooks/useTimoutFn";

export default {
  title: "Hook/useTimeoutFn",
};

export const Default = () => {
  const [run, clear] = useTimeoutFn(() => {
    alert("실행!");
  }, 3000);

  return (
    <>
      <div>useTimeoutFn 테스트</div>
      <button onClick={run}>3초 뒤 실행!</button>
      <button onClick={clear}>멈춰!</button>
    </>
  );
};

위의 예시 코드는 3초 뒤 실행 버튼을 클릭하면 alert로 실행 문구가 출력된다.
만약 실행 버튼을 누르고 취소하고 싶다면 3초 안에 멈춰 버튼을 누르게 되면 이벤트가 종료되어 alert 실행을 멈출 수 있다.

 

✍ 2. 컴포넌트가 로딩 된 후 바로 실행되는 방법 (useTimeOut)

이 경우에는 위에 작성한 useTimeOutFn useHook을 이용하면 간단하다.

import { useEffect } from "react";
import useTimeoutFn from "./useTimoutFn";

const useTimout = (fn, ms) => {
  // 정의한 useTimeoutFn Hook 사용
  const [run, clear] = useTimeoutFn(fn, ms);

  // 바로 실행 후 종료
  useEffect(() => {
    run();
    return clear;
  }, [run, clear]);

  // 컴포넌트가 로딩 된 후 바로 실행하므로
  // 이것을 취소해주는 clear만 반환
  return clear;
};

export default useTimout;

📚 useTimeOut - StoryBook 코드

import useTimeout from "../../hooks/useTimeout";

export default {
  title: "Hook/useTimeout",
};

export const Default = () => {
  const clear = useTimeout(() => {
    alert("실행!");
  }, 3000);

  return (
    <>
      <div>useTimeout 테스트</div>
      <button onClick={clear}>멈춰!</button>
    </>
  );
};

위의 예시는 컴포넌트가 실행되자마자 3초 후 alert("실행") 문구를 띄운다.

만약 실행되자마자 이벤트를 막기 위해서는 멈춰 버튼을 클릭하면 된다.

 

👨‍💻 사실 리액트 과정부터 학습하기 바빠서 포스팅을 잠시 멈췄다가 과정이 끝난 이후 다시 포스팅을 이어나가고 있다.
그래서 복습을 위해 다시 강의를 듣고 코드를 분석하면서 온전히 이해하면서 포스팅을 하고 있는데 예전보다 지금 더 이해가 잘 되는 느낌이고 라인 바이라인을 이해할 수 있게 되었다.
그 당시에는 진도 따라잡기 바빠 중요한 내용들을 많이 놓치고 있었던 것 같다. 아마 블로그 포스팅이 아니었으면 계속 놓치고 살았던 정보들을 이번 기회를 통해 다시금 학습할 수 있어서 좋았다.

 

📖 학습한 내용

  • React(7) - 사용자 정의 Hook 연습하기
    • useKey, useKeyPress
    • useClickAway
    • useResize
    • useLoaclStorage, useSessionStorage
    • useForm
    • useTimeOut
    • useInterval
728x90

'프로그래머스 데브코스_FE > TIL' 카테고리의 다른 글

[React] React(9)  (0) 2022.01.28
[React] React(8)  (0) 2022.01.28
[React] React(6)  (0) 2022.01.26
[React] React(5)  (0) 2022.01.24
[React] React(4)  (0) 2022.01.23
Comments