React 텍스트 Editor 라이브러리

정지훈·2025년 3월 10일
0

velog나 다른 텍스트를 편집할때 에디터를 만들고 싶어 라이브러리를 서치하던 도중
react-quill, @tiptap/react ,@tiptap/starter-kit 이 라이브러리를 사용해 보았다.

처음 react-quill을 사용을 해 보았는데

<ReactQuill
        ref={quillRef}
        theme="snow"
        value={value}
        onChange={handleOnChange}
        modules={modules}
        formats={formats}
        placeholder={placeholder}
        scrollingContainer={document.body}
      />

이런식으로 사용법이 편리하였다.
formats는

  const formats = ["bold", "italic", "underline", "header", "image"];

이런식으로 폰트 굵기 이테릭,언더라인,해더로 formats를 지정해주고

const modules = useMemo(
    () => ({
      toolbar: false,
      keyboard: {
        // bindings: {
        //   paste: {
        //     key: 'V',
        //     shortKey: true,
        //     handler: function() {
        //       // 기본 붙여넣기 동작 허용
        //       return true;
        //     }
        //   }
        // }
      },
    }),
    []
  );

이런식으로 modules를 이용해 option을 지정할 수 있다.

https://www.npmjs.com/package/react-quill

하지만 이 라이브러리가 다른 사이트에서 복사한 글을 붙여넣기 할 때 계속 맨 위로 올라가서

  const handleOnChange = useCallback<TextEditorProps["onChange"]>(
    (value, delta, source, editor) => {
      if (
        source === "user" &&
        delta.ops?.some(
          (op) =>
            op.insert && typeof op.insert === "string" && op.insert.length > 1
        )
      ) {
        // 붙여넣기 시 현재 스크롤 위치와 커서 위치 저장
        const currentScrollPosition = window.scrollY;
        const selection = quillRef.current?.getEditor().getSelection();

        // 스크롤과 커서 위치 복원
        setTimeout(() => {
          window.scrollTo({
            top: currentScrollPosition,
            behavior: "auto",
          });
          if (selection) {
            quillRef.current?.getEditor().setSelection(selection);
          }
        }, 0);
      }
      onChange(value, delta, source, editor);
    },
    [onChange]
  );

이 코드를 짜보았고 그래도 똑같은 현상이 일어나서 왜이러지? 라고 생각이 들어 별 방법을 쓰고 chat gpt한테도 물어도 보았는데 해결이 안되어서 다른 라이브러리인 @tiptap/react ,@tiptap/starter-kit 이것을 사용 하였다.
https://tiptap.dev/

사용법은 quill과 같이 간편하게 설정할 수 있었고

      <EditorContent editor={editor} />

이렇게 넣어준 후 editor에는

  const editor = useEditor({
    extensions: [
      StarterKit,
      Image.configure({
        inline: true,
        HTMLAttributes: {
          class: "editor-image",
        },
      }),
    ],
    content: value,
    onUpdate: ({ editor }) => {
      const html = editor?.getHTML();
      const textContent = editor?.getText() || "";
      if (textContent) {
        setIsFocus(true);
      }
      setCharacterCount(textContent.length);

      const mockDelta = {} as DeltaStatic;
      const mockSource = "user" as Sources;
      const mockEditor = {} as UnprivilegedEditor;

      onChange(html, mockDelta, mockSource, editor);
    },
    editorProps: {
      attributes: {
        class: "tiptap-editor",
        placeholder,
      },
    },
  });

이런식의 훅이 있어서 옵션과 update를 사용하여 이용 할 수 있었고 quill에서 발생한 오류는 발생하지 않아서 다행이었다..

0개의 댓글