프론트엔드 비즈니스 로직 분리 - boostcampwm-2022/web30-TODY GitHub Wiki
💡 프론트엔드에서 비동기 API 요청, 입력 유효성 검증과 같은 비즈니스 로직을 분리하고 효율적으로 관리하기 위해 React Custom Hooks를 사용했습니다.
- 컴포넌트의 UI 로직과 비즈니스 로직을 분리한다.
- API 호출, 입력 유효성 검증과 같은 반복되는 비즈니스 로직을 분리하여 재사용성을 높인다.
- 리액트 커스텀 훅 사용
-
공부방 페이지 컴포넌트의 UI 로직과 비즈니스 로직 분리를 위해 커스텀 훅을 만들어 적용했다. ( 공부방 페이지 컴포넌트 내부 코드 : 436줄 → 91줄)
-
useSfu
- WebRTC SFU방식 연결을 위한 로직
-
useStudyRoomPage
- 공부방 정보, 하단바, 사이드바 활성 상태 로직
-
useSfu
-
반복되는 비즈니스 로직의 재사용성을 위해 커스텀 훅을 만들어 적용했다.
-
useAxios<T>
-
코드로 살펴보기
import axios, { AxiosPromise } from 'axios'; import { useCallback, useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; export default function useAxios<T>( axiosFunction: (arg?: any) => AxiosPromise<T>, options?: { onMount?: boolean; arg?: any; errNavigate?: boolean }, ): [ (arg?: any) => Promise<void>, boolean, { statusCode: number | undefined; message: any; error: string; } | null, T | null, ] { const onMount = options?.onMount || false; const argument = options?.arg || undefined; const errNavigate = options?.errNavigate ?? true; const [loading, setLoading] = useState<boolean>(onMount); const [error, setError] = useState<{ statusCode: number | undefined; message: any; error: string; } | null>(null); const [data, setData] = useState<T | null>(null); const navigate = useNavigate(); useEffect(() => { if (!error) return; if (errNavigate) navigate('/error', { state: error }); }, [error]); const request = useCallback( async (arg?: any) => { setLoading(true); setError(null); setData(null); try { const response = await axiosFunction(arg); setData(response.data); } catch (err) { if (axios.isAxiosError(err)) { if (err.response) { setError(err.response.data); } else { setError({ statusCode: undefined, message: err.message, error: err.message, }); } } } setLoading(false); }, [axiosFunction], ); useEffect(() => { if (!onMount) return; request(argument); }, []); return [request, loading, error, data]; }
-
API 요청 및 비동기 데이터 상태 로직
-
인자 : axios로 API 호출 후 AxiosPromise<T>를 반환하는 함수
- /axios/requests 폴더에 API 호출 함수들을 분리
-
반환 값 : [
request
,loading
,error
,data
]-
request
: wrapping된 API 호출 함수 (function) -
loading
: loading에 대한 상태 값 (boolean) -
error
: error에 대한 상태 값 (object | null) -
data
: success시 받아온 데이터 (T | null)
-
-
옵션
-
onMount
: 컴포넌트 초기 렌더링 후 API 요청 자동화 여부 (boolean) -
errNavigate
: error 응답 시 에러페이지로의 이동 여부 (boolean)
-
-
-
useInputValidation
-
코드로 살펴보기
import React, { useState } from 'react'; export default function useInputValidation( callback: (value: string) => boolean, initialValue: string, ): [(e: React.ChangeEvent<HTMLInputElement>) => void, boolean] { const [isValidated, setIsValidated] = useState(callback(initialValue)); const validateInputValue = (e: React.ChangeEvent<HTMLInputElement>) => { const { value } = e.currentTarget; setIsValidated(callback(value)); }; return [validateInputValue, isValidated]; }
-
Input 요소의 유효성 검증 로직을 담당
-
인자 : input 요소 value 검증 후 boolean을 반환하는 함수
-
반환 값 : [
validateValue
,isValueValidated
]-
validateValue
: input 요소의 onChange 핸들러 (function) -
isValueValidated
: input 요소 value의 validation 결과 값 (boolean)
-
-
-
useAxios<T>