ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] Custom Hook을 사용하자
    Web/Front-End 2021. 5. 20. 11:57

    Custom Hook은 아주 편한 기능 중 하나이다.

    내가 사용하고싶은 컴포넌트나 로직을 미리 정의해두고 매개변수를 통해 자유롭게 어디서든 가져다 쓸 수 있으면서 Hook 내부에는 react문법이나 다른 hook을 포함 시킬 수 있어 함수형 컴포넌트 개발을 하면 빼먹을수가 없는 부분이다.

     

    간단하게 내가 만든 예제를 통해 뭐가 간편한지 작성하도록 하겠다.

     

    const usePage = () => {
    	const [totalSize, setTotalSize] = useState(0)
    	const [size, setSize] = useState(10)
    	const [pageNumber, setPageNumber] = useState([])
    	const [selectedPage, setSelectedPage] = useState(1)
    
    	const [maxPage, setMaxPage] = useState(10)
    	const [pageBundle, setPageBundle] = useState(1)
    	const [currentBundle, setCurrentBundle] = useState(1)
    
    	useEffect(() => {
    		return () => {
    			setTotalSize(0)
    			setSize(10)
    			setPageNumber([])
    			setSelectedPage(1)
    			setMaxPage(10)
    			setPageBundle(1)
    			setCurrentBundle(1)
    		}
    	}, [])
    
    	useEffect(() => {
    		setPageNumber([])
    		const perValue = totalSize / size
    		const decimal = Math.floor(perValue)
    		if (perValue > decimal) {
    			calcPageNumber(decimal + 1)
    		} else calcPageNumber(decimal)
    
    	}, [totalSize])
    
    	useEffect(() => {
    		if (pageNumber.length > maxPage) {
    			const perValue = pageNumber.length / maxPage
    			const decimal = Math.floor(perValue)
    			if (perValue > decimal) {
    				setPageBundle(decimal + 1)
    			} else setPageBundle(decimal)
    		}
    	}, [pageNumber.length])
    
    	useEffect(() => {
    		const bundlePer = selectedPage / maxPage
    		const bundleDecimal = Math.floor(bundlePer)
    
    	 if (bundlePer > bundleDecimal) {
    	 	setCurrentBundle(bundleDecimal + 1)
    	 } else setCurrentBundle(bundleDecimal)
    	}, [selectedPage])
    
    	const calcPageNumber = (number) => {
    		for (let i = 1; i <= number; i++) {
    			setPageNumber(pageNumber => pageNumber.concat(i))
    		}
    	}
    
    	const pagingComponent = (bundle) => pageNumber.map((numberItem) => {
    		if (maxPage * bundle >= numberItem && bundle <= pageBundle && numberItem > (bundle - 1) * maxPage) {
    			return (
    				<li className={selectedPage === numberItem ? 'on paging_num' : 'paging_num'} key={numberItem}>
    					<a onClick={() => setSelectedPage(numberItem)}>{numberItem}</a>
    				</li>
    			)
    		}
    	})
    
    	return (
    		[<div className="paging clear martop_20">
    			<ul>
    				<li className={selectedPage !== 1 ? 'paging_first on' : 'paging_first'} key={'first'}>
    					<a
    						style={selectedPage !== 1 ? { cursor: 'pointer' } : { cursor: 'default' }}
    						onClick={() => setSelectedPage(1)}
    					/>
    				</li>
    				<li className={selectedPage !== 1 ? 'paging_prev on' : 'paging_prev'} key={'prev'}>
    					<a
    						style={selectedPage !== 1 ? { cursor: 'pointer' } : { cursor: 'default' }}
    						onClick={selectedPage !== 1 ? () => setSelectedPage(selectedPage - 1) : null}
    					/>
    				</li>
    				{pagingComponent(currentBundle)}
    				<li className={pageNumber.length === selectedPage ? 'paging_next' : 'paging_next on'} key={'next'}>
    					<a
    						style={pageNumber.length === selectedPage ? { cursor: 'default' } : { cursor: 'pointer' }}
    						onClick={pageNumber.length === selectedPage ? null : () => setSelectedPage(selectedPage + 1)}
    					/>
    				</li>
    				<li className={pageNumber.length === selectedPage ? 'paging_last' : 'paging_last on'} key={'last'}>
    					<a
    						style={pageNumber.length === selectedPage ? { cursor: 'default' } : { cursor: 'pointer' }}
    						onClick={pageNumber.length === selectedPage ? null : () => setSelectedPage(pageNumber.length)}
    					/>
    				</li>
    			</ul>
    		</div>, setTotalSize, size, selectedPage]
    	)
    
    }
    
    export default usePage

    언젠가 작성했던 Page Hook이다. 

     

    해당 훅은 

    화면에서 보면 이렇게 생겼다. 

    state를 통해 현재 페이지와 한 페이지 안에 들어갈 레코드 수, 한 번들안에서 보여줄 최대 페이지의 개수등을 관리한다.

    그냥 그런 로직이다. 퍼블리싱이 잘 되어서 별다른 로직은 필요가 없었지만 state만 바꿔주는 코드량도 만만치 않게길긴해서 페이징을 쓰는 화면마다 도저히 붙일 수 가 없을 것 같아 hook으로 처리하였다.

     

    실제 코드에서 page를 쓰려면

    const [pagingComponent, setTotalSize, size, selectedPage] = usePage()
    
    useEffect(()=> {
    	//페이지가 바뀔때 로직처리
    },[selectedPage, size])

    이게 끝이다.

     

    불필요한 중복 코드 작성을 최소화하며, 리액트를 리액트답게 쓸 수 있는 좋은 기능이라 생각하여

    굉장히 애용하고있다.

    댓글

Designed by Tistory.