컴포넌트의 덩치를 줄이는 방법

Kyung·2023년 4월 23일
0

동기

한달 두달 전에 짠 코드를 기능 추가, 수정의 이슈로 수정하는 경우가 빈번해졌는데, 내가 짠 코드여도 컴포넌트에 여러 로직이 뒤섞여 있어 코드의 흐름 파악을 하는데 있어 시간이 많이 걸렸다. 그래서 관심사별로 코드를 분리하여 컴포넌트의 덩치를 줄여보는 시도를 하게 되었다.

기존 코드 상황

  1. 리액트 쿼리 로직이 컴포넌트 안에서 모두 구현되어 있었다.
  2. 모달의 경우 전역 상태로 관리하지 않고 컴포넌트에서 visible state로 관리하였다.
    • 만약 모달이 여러개일 경우 -> 모달 개수만큼 state를 정의해주어야한다
  3. 분리할 수 있는 관심사의 것들이 하나의 컴포넌트에 담겨 있다.
const Example = () => {
	const [x, setX] = useState('')
	const [y, setY] = useState('')
	const [visible1, setVisible1] = useState(false)
	const [visible2, setVisible2] = useState(false)
	const { data, isLoading } = useQuery(['example', x, y], () => getSomething(x, y), {
		select(data){
			return data.map((element) => ({
				...
			}))
		}
	})

	useEffect(() => {
		document.title = x
	},[x])

	const handleXChange = (e: React.ChangeEvent<HTMLInputElement>) => {
		setX(e.target.value)
	}

	const handleYChange = (e: React.ChangeEvent<HTMLInputElement>) => {
		setY(e.target.value)
	}

	const handleOpenModal1Click = () => {
		setVisible1(true)
	}

	const handleOpenModal2Click = () => {
		setVisible2(true)
	}

	return (
		<div>
			<input value={x} onChange={handleXChange}/>
			<input value={y} onChange={handleYChange}/>
			<button onClick={handleOpenModal1Click}>open modal1</button>
			<button onClick={handleOpenModal2Click}>open modal2</button>
			{visible1 && <Modal1/>}
			{visible2 && <Modal2/>}
		</div>
	)
} 

개선

  1. 리액트 쿼리에 대한 상세 로직을 컴포넌트 단에서는 알 수 없도록 추상화시킨다.
  2. 모달의 경우, 전역 상태로 관리한다.
  3. 비슷한 것끼리 묶는다.
    • 커스텀 훅
    • 컴포넌트 추상화

개선한 코드

Exampe.tsx

const Example = () => {
	const { x, y, handleXChange, handleYChange } = useXY()
	const { data } = useGetSomethingQuery(x, y)
	
	return (
		<div>
			<input value={x} onChange={handleAChange}/>
			<input value={y} onChange={handleBChange}/>
			{data}
			<ModalButtons/>
		</div>
	)
} 

useXY.ts

const useXY = () => {
	const [x, setX] = useState('')
	const [y, setY] = useState('')

	useEffect(() => {
		document.title = x
	},[x])
	
	const handleXChange = (e: React.ChangeEvent<HTMLInputElement>) => {
		setX(e.target.value)
	}

	const handleYChange = (e: React.ChangeEvent<HTMLInputElement>) => {
		setY(e.target.value)
	}

	return { x, y, handleXChange, handleYChange }
}

export default useXY

useGetSomethingQuery.ts

const useGetSomethingQuery(x: string, y: string) => {
	return useQuery(['example', x, y], () => getSomething(x, y), {
		select(data){
			return data.map((element) => ({
				...
			}))
		}
	})
}

export default useGetSomethingQuery

ModalButtons.tsx

const ModalButtons = () => {
	const openModal = useSetAtom(modalsAtom)

	const handleOpenModal1Click = () => {
		openModal({
			component: <Modal1/>,
			props: {...},
		})
	}

	const handleOpenModal2Click = () => {
		openModal({
			component: <Modal2/>,
			props: {...},
		})
	}

	return (
			<button onClick={handleOpenModal1Click}>open modal1</button>
			<button onClick={handleOpenModal2Click}>open modal2</button>
	)
}

export default ModalButtons

구현 설명

  1. 리액트 쿼리의 상세 로직을 useGetSomethingQuery함수에 담아 추상화시켰다.
  2. 비슷한 관심사끼리 묶어 useXY라는 커스텀훅으로 추상화시켰다.
  3. 모달 관련 로직은 x,y 입력과 다른 관심사이므로 컴포넌트로 만들어 추상화시켰다.
  4. 모달 상태의 경우, 전역 상태로 관리하였다.

효과

  • 로직 흐름 파악이 쉬워졌다.
  • 비슷한 관심사 끼리 로직이 모여 있으므로 수정할 부분을 찾기가 수월해졌다.
profile
개발 일지를 작성합니다

0개의 댓글