blog_ag 프로젝트를 진행하며 생겼던 ReactQuill 관련 에러 및 해결을 기록한 글입니다.

프로젝트 제작 중, 리액트의 텍스트 에디터 라이브러리인
react-quill을 사용하였다. 이 라이브러리의 기능 중 하나인 이미지 삽입에 대하여, 사이즈 조절이 되지 않는 문제점을quill-image-resize를 이용하여 해결하려 했지만 잘 되지 않아 등록한 이슈이다.
npm install react-quill"^2.0.0"npm install quill-image-resize-module-ts"^3.0.3"src/components/textEditor.tsx
import dynamic from "next/dynamic";
import ReactQuill from "react-quill";
import hljs from "highlight.js/lib/core";
import javascript from "highlight.js/lib/languages/javascript";
import python from "highlight.js/lib/languages/python";
import typescript from "highlight.js/lib/languages/typescript";
import c from "highlight.js/lib/languages/c";
import ImageResize from. "quill-image-resize"
const Quill_NoSSR = dynamic(import("react-quill"), {
ssr: false,
loading: () => <p>Loading...</p>,
});
hljs.registerLanguage("javascript", javascript);
hljs.registerLanguage("python", python);
hljs.registerLanguage("typescript", typescript);
hljs.registerLanguage("c", c);
const modules = {
syntax: {
highlight: (text: any) => hljs.highlightAuto(text).value,
},
toolbar: [
[{ header: [1, 2, false] }, { header: "2" }, { font: [String] }],
[{ size: [String] }],
["bold", "italic", "underline", "strike", "blockquote"],
[
{ list: "ordered" },
{ list: "bullet" },
{ indent: "-1" },
{ indent: "+1" },
],
["link", "image", "video", "code-block"],
["clean"],
],
};
const formats = [
"header",
"font",
"size",
"bold",
"italic",
"underline",
"strike",
"blockquote",
"list",
"bullet",
"indent",
"link",
"image",
"video",
"code-block",
];
const TextEditor = (props: any) => {
const { content, setContent } = props;
return (
<Quill_NoSSR
modules={modules}
formats={formats}
theme={"snow"}
value={content}
placeholder={"Please Write a Content!"}
onChange={(content, delta, source, editor) =>
setContent(editor.getHTML())
}
/>
);
};
export default TextEditor;
우선 위의 코드에서 ImageResize 모듈을 등록하기 위해
Quill_NoSSR.register("modules/ImageResize, ImageResize")
라는 코드를 작성하게 되면, Quill_NoSSR에는 register라는 property가 없다는 에러 메시지가 출력된다.
이 문제를 해결하기위해 수많은 구글링을 실시했지만, 딱히 참고할만한 레퍼런스가 존재하지 않았다.
알고보니, 내가 위에서 선언한 Quill_NoSSR이라는 변수는 Next의 dynamic import를 통하여 가져온 변수이기 때문에, Quill 또는 ReactQuill같은 라이브러리 컴포넌트와 달리 register라는 property가 존재 하지 않았던 것이다.
따라서, dynamic import를 실시하는 위치를 바꿔주면 자연스럽게 해결 될 것이라는 생각이 들어, 현재 textEditor 컴포넌트에서 import 하던것을, textEditor를 자식으로 가지고있는 컴포넌트에서 실시하기로 하였다.
quill의 ImageResize 모듈 적용시 발생한 에러이다.
addRange(): The given range isn't in document.
src/components/textEditor.tsx
import ReactQuill from "react-quill";
import hljs from "highlight.js/lib/core";
import javascript from "highlight.js/lib/languages/javascript";
import python from "highlight.js/lib/languages/python";
import typescript from "highlight.js/lib/languages/typescript";
import c from "highlight.js/lib/languages/c";
import ImageResize from. "quill-image-resize"
const modules = {
syntax: {
highlight: (text: any) => hljs.highlightAuto(text).value,
},
toolbar: [
[{ header: [1, 2, false] }, { header: "2" }, { font: [String] }],
[{ size: [String] }],
["bold", "italic", "underline", "strike", "blockquote"],
[
{ list: "ordered" },
{ list: "bullet" },
{ indent: "-1" },
{ indent: "+1" },
],
["link", "image", "video", "code-block"],
["clean"],
],
};
const formats = [
"header",
"font",
"size",
"bold",
"italic",
"underline",
"strike",
"blockquote",
"list",
"bullet",
"indent",
"link",
"image",
"video",
"code-block",
];
const TextEditor = (props: any) => {
const { content, setContent } = props;
return (
<ReactQuill
modules={modules}
formats={formats}
theme={"snow"}
value={content}
placeholder={"Please Write a Content!"}
onChange={(content, delta, source, editor) =>
setContent(editor.getHTML())
}
/>
);
};
export default TextEditor;
src/pages/post/index.tsx
import dynamic from "next/dynamic";
// TextEditor를 자식으로 가지는 컴포넌트에 대하여 dynamic import를 실시한다.
const TextEditor = dynamic(() => import("../../components/textEditor"), {
ssr: false,
});
export default function Post() {
const [content, setContent] = useState("");
return (
<>
<div className="col-lg-3 col-md-6 text-center">
<TextEditor content={content} setContent={setContent} />
</div>
</>
);
}
위의 코드처럼 TextEditor를 자식으로 가지는 컴포넌트에 대하여 dynamic import를 실시하고, textEditor 컴포넌트에서는 ReactQuill을 사용하여 컴포넌트를 구성하였다.
이렇게 코드를 작성함으로써, ImageResize 같은 Quill 관련 라이브러리를 register 할 수 있게 되었다.
src/components/textEditor.tsx
const modules = useMemo(() => {
return {
syntax: {
highlight: (text: any) => hljs.highlightAuto(text).value,
},
toolbar: [
[{ header: [1, 2, false] }, { header: "2" }, { font: [String] }],
[{ size: [String] }],
["bold", "italic", "underline", "strike", "blockquote"],
[
{ list: "ordered" },
{ list: "bullet" },
{ indent: "-1" },
{ indent: "+1" },
],
["link", "image", "code-block"],
["clean"],
],
ImageResize: { modules: ["Resize"] },
};
}, []);
해당 에러에 대하여 구글링해보니, 정의된 modules들이 렌더링마다 매번 생성되고 있기 때문에 발생한 에러라고 한다.
따라서, 기존에 그냥 선언하였던 modules를 useMemo Hook을 이용하여 선언해주면 해결된다..