React — 두 목록 사이 이동
항목을 같은 목록 안에서 재정렬하거나 다른 목록으로 이동합니다. 두 영역은 같은 scope와 group="tasks"를 공유하고 각 areaId는 고유합니다. 항목 ID는 이동 후에도 유지됩니다.
직접 실행
섹션 제목: “직접 실행”항목 왼쪽 손잡이를 잡고 오른쪽 빈 목록에 놓으십시오. 완료 수가 늘어나고 왼쪽 목록에서 해당 항목이 제거됩니다. 초기화는 모든 항목을 원래 순서로 되돌립니다. 이 예제의 이동 조작은 포인터 기반입니다.
import { useState } from 'react';import { SortableRoot, SortableArea } from 'comins-sortable/react';
type Item = { id: string; label: string };export default function ReactTransfer({ lang = 'ko' }: { lang?: string }) { const ko = lang === 'ko'; const initial = [{ id: 'plan', label: ko ? '문서 설계' : 'Design the docs' }, { id: 'build', label: ko ? '예제 구현' : 'Build an example' }, { id: 'review', label: ko ? '코드 검토' : 'Review the code' }]; const [todo, setTodo] = useState<Item[]>(initial); const [done, setDone] = useState<Item[]>([]); return <div className="demo" data-demo="sortable-react"> <div className="demo-toolbar"><span>{ko ? '손잡이를 잡고 다른 목록으로 이동하세요.' : 'Drag a handle into the other list.'}</span><button onClick={() => { setTodo(initial); setDone([]); }}>{ko ? '초기화' : 'Reset'}</button></div> <SortableRoot<Item>> <div className="transfer-board"> {[{ id: 'todo', title: ko ? '진행 예정' : 'To do', items: todo, update: setTodo }, { id: 'done', title: ko ? '완료' : 'Done', items: done, update: setDone }].map(list => <section key={list.id} className="transfer-column"> <div className="list-heading">{list.title}<span>{list.items.length}</span></div> <SortableArea<Item> areaId={list.id} group="tasks" items={list.items} itemKey="id" handle=".task-handle" onItemsChange={next => list.update([...next])} areaProps={{ className: 'task-list', 'aria-label': list.title }}> {item => <div className="task" data-task={item.id}><button className="task-handle" aria-label={`${ko ? '드래그' : 'Drag'}: ${item.label}`}>⠿</button><span>{item.label}</span></div>} </SortableArea> </section>)} </div> </SortableRoot> <p role="status" className="demo-status">{ko ? '완료' : 'Done'}: {done.length} / 3</p> </div>;}React 상태 계약
섹션 제목: “React 상태 계약”SortableRoot가 공유 scope를 소유합니다. SortableArea의 items, itemKey, onItemsChange를 연결합니다. 이동 시 양쪽 목록의 callback이 제공하는 배열을 각각 상태에 반영합니다. children(item, index)는 항목 React 요소를 반환하는 render prop입니다. 이 계약은 Vue의 동일한 컴포넌트 이름과 구분됩니다.
각 핸들의 touch-action: none과 user-select: none은 드래그 중 터치 스크롤·텍스트 선택 충돌을 줄입니다.
검색어
섹션 제목: “검색어”다른 목록으로 이동, 목록 간 이동, 항목 옮기기, 드래그 앤 드롭, 재정렬, 공유 scope, transfer.