[React] 드래그 가능한 사이즈 조절 컴포넌트 구현

728x90
반응형

useState와 이벤트 리스너를 활용한 커서 기반 사이즈 조절 기능 구현함

 

import { useEffect, useState } from 'react';
import './App.css';
import LeftContent from './components/LeftContent';
import RightContent from './components/RightContent';
import './index.css';
import { checkPrimeSync } from 'crypto';
import { AnySoaRecord } from 'dns';

function App() {
    const [width, setWidth] = useState(200);
    const [isDragging, setIsDragging] = useState(false);

    const handleMouseDown = () => {
        setIsDragging(true);
        document.body.style.cursor = 'col-resize';
    };

    const handleMouseMove = (e: any) => {
        if (!isDragging) return;
        e.preventDefault();
        e.stopPropagation();

        const xNumber = e.clientX;
        setWidth(xNumber);
    };

    const handleMouseUp = () => {
        setIsDragging(false);
        document.body.style.cursor = 'default';
        document.removeEventListener('mousemove', handleMouseMove);
        document.removeEventListener('mouseup', handleMouseUp);
    };

    useEffect(() => {
        if (isDragging) {
            document.addEventListener('mousemove', handleMouseMove);
            document.addEventListener('mouseup', handleMouseUp);
        } else {
            document.removeEventListener('mousemove', handleMouseMove);
            document.removeEventListener('mouseup', handleMouseUp);
        }

        return () => {
            document.removeEventListener('mouseup', handleMouseUp);
            document.removeEventListener('mousemove', handleMouseMove);
        };
    }, [isDragging]);

    return (
        <div className="flex ">
            <div className="flex " style={{ width: `${width}px` }}>
                <LeftContent />
                <div
                    className="bg-red-400 w-[3px] px-[10px] hover:cursor-col-resize"
                    onMouseDown={handleMouseDown}
                ></div>
            </div>
            <div className="flex-1">
                <RightContent />
            </div>
        </div>
    );
}

export default App;

 

1) 마우스가 div 밖으로 나가도 크기 조절 가능

* mousemove & mouseup 이벤트 : 전역(document)에 등록

* mousedown : div에서 발생

 

2) mouseup인데도 계속 드래그 됨

* mouseup 이벤트는 드래그가 끝날때마다 제거해야함 

* 동시에 mousemove & mouseup 이벤트리스너도 제거

 

3) 커서 모양이 변경됨 && 움직일때마다 깜빡거림

* 자바스크립트로 동적 커서 모양 변경

    const handleMouseDown = () => {
        setIsDragging(true);
        document.body.style.cursor = 'col-resize';
    };
    
    
    
    const handleMouseUp = () => {
        setIsDragging(false);
        document.body.style.cursor = 'default';
        document.removeEventListener('mousemove', handleMouseMove);
        document.removeEventListener('mouseup', handleMouseUp);
    };

 

 

 

3-1) after 가상요소 사용하기 

    return (
        <div className="flex ">
            <div className="flex " style={{ width: `${width}px` }}>
                <LeftContent />
                <div
                    className="relative
                     bg-red-400 w-[3px]  hover:cursor-col-resize 
                     after:absolute after:top-0 after:right-[-3px] after:w-[10px] after:h-full after:cursor-col-resize "
                    onMouseDown={handleMouseDown}
                ></div>
            </div>
            <div className="flex-1">
                <RightContent />
            </div>
        </div>
    );
반응형