Next.js의 서버 사이드 렌더링(SSR)과 react-beautiful-dnd(@hello-pangea/dnd)의 호환성 문제로 초기 렌더링 시에 data-rbd-draggable-context-id did not match.
경고가 발생했다.
import dynamic from 'next/dynamic';
const Droppable = dynamic(
() => import('@hello-pangea/dnd').then(mod => mod.Droppable),
{ ssr: false }
);
const Draggable = dynamic(
() => import('@hello-pangea/dnd').then(mod => mod.Draggable),
{ ssr: false }
);
next/dynamic
을 사용하여 Droppable과 Draggable 컴포넌트를 동적으로 임포트하고, { ssr: false } 옵션을 통해 이들이 클라이언트 사이드에서만 로드되도록 설정했다. 이 방법으로 서버와 클라이언트 사이의 불일치 문제를 해결하였다.
Next.js 같은 서버 사이드 렌더링을 지원하는 프레임워크에서 dynamic 함수를 사용하여 컴포넌트를 동적으로 로드하는 경우, 이 로드 과정은 브라우저가 페이지를 불러온 후, 클라이언트에서 발생한다.
getServerSideProps
를 적용하지 않았는데도 서버 사이드 렌더링을 하는 이유 Next.js는 페이지를 방문하는 첫번째 요청에 대해 자동으로 서버에서 페이지를 렌더링한다.
사용자가 li 태그의 전체 영역이 아니라, 일정부분에서만 드래그를 할 수 있었다. input 요소가 drag & drop 동작을 방해한 것으로 판단했다.
todo-list안의 todo-item은 props로 disabled 속성을 전달했었고, 이들은 input 요소로서 쓰일 필요가 없기 때문에 span 태그로 대체하였다.
export default function TodoItem({
checked,
handleCheckboxChecked,
className,
children,
...props
}: IProps) {
return (
<div
className={clsx(styles.item, className)}
>
<CheckboxButton
className={styles['checkbox-button']}
checked={checked}
onChange={handleCheckboxChecked}
/>
{
props.disabled ?
<span
className={clsx(
{
[styles.checked]: checked,
[styles.disabled]: props.disabled
}, styles.input)}
>
{props.value}
</span>
:
<input
className={clsx(
{
[styles.checked]: checked,
[styles.disabled]: props.disabled
}, styles.input)}
{...props}
/>
}
{children}
</div>
);
}