TipTap React:根据下拉选择更新编辑器初始内容

ajh*_*ery 1 reactjs next.js tiptap

我使用 TipTap 作为我的 React 项目的富文本编辑器,用于更新从下拉列表中选择的产品的描述。

预期结果是编辑器应显示已保存在相应产品数据库中的初始内容。

但是,使用编辑器中的“内容”选项允许我设置初始内容,如果我更改下拉列表中的选项,它不会更新初始内容。

更新数据

我的编辑器代码:

import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import Underline from '@tiptap/extension-underline';
import Placeholder from '@tiptap/extension-placeholder';
import TipTapMenubar from './TipTapMenubar';

const TiptapEditor = ({ description, setDescription }) => {
  // console.log('description', description);

  const sampleDesc = `Describe your product in 4-5 bullet points...
    Point #1: this is an explanation of my product.
    Point #2: ....`;

  const editor = useEditor({
    extensions: [
      StarterKit,
      Underline,
      Placeholder.configure({
        placeholder: sampleDesc,
      }),
    ],
    content: `${description}`,
    onUpdate: ({ editor }) => {
      const html = editor.getHTML();
      setDescription(html);
    },
  });

  return (
    <div className='!mt-2 border border-gray-300 shadow rounded'>
      <TipTapMenubar editor={editor} />
      <EditorContent editor={editor} />
    </div>
  );
};

export default TiptapEditor;
Run Code Online (Sandbox Code Playgroud)

然后在父组件中调用此编辑器组件来显示数据:

import { useState, useEffect } from 'react';
import Skeleton from 'react-loading-skeleton';
import TiptapEditor from '@/components/common/editor/TiptapEditor';
import InputInlineLabel from '@/components/form/InputInlineLabel';
import LoadingButton from '@/components/form/LoadingButton';

function ProductOptionNameDesc({
  product,
  selectedOption,
  name,
  setName,
  description,
  setDescription,
  loading,
  handleProductOptionData,
  handleProductOptionsDescription,
}) {
  const [enableEditor, setEnableEditor] = useState(false);
  // console.log('product', product);
  // console.log('selectedOption', selectedOption);
  // if selectedOption, set name and description from it
  useEffect(() => {
    if (selectedOption) {
      const productOptions = product?.product_options;
      productOptions?.map((option) => {
        if (option?.id === selectedOption?.id) {
          setName(option?.name);
          setDescription(option?.description);
        }
      });
      setEnableEditor(true);
    }
  }, [selectedOption]);

  // console.log('description', description);

  return (
    <div>
      <form onSubmit={handleProductOptionData}>
        <div className='space-y-4'>
          <div className='flex items-center gap-2'>
            <label htmlFor='poname' className='text-sm text-gray-600'>
              Product option name
            </label>
            <input
              id='poname'
              name='poname'
              placeholder='product name'
              className='w-full rounded p-2 border border-gray-300 text-sm placeholder:text-sm focus:outline-none focus:border-purple-500'
              value={name || ''}
              onChange={(e) => setName(e.target.value)}
            />
          </div>
          <div className='space-y-2'>
            {enableEditor ? (
              <TiptapEditor
                description={description}
                setDescription={setDescription}
                placeholder='Add up to 5 points describing the product...'
              />
            ) : (
              <div>
                <Skeleton height={20} />
                <Skeleton height={70} />
              </div>
            )}
          </div>

            {loading ? (
              <LoadingButton />
            ) : (
              <button className='text-sm w-full py-1 px-2 rounded cursor-pointer border border-violet-700 bg-violet-50 hover:bg-violet-100 text-violet-700'>
                Update name and description
              </button>
            )}
        </div>
      </form>
    </div>
  );
}

export default ProductOptionNameDesc;
Run Code Online (Sandbox Code Playgroud)

我想要实现的目标:

如果用户在下拉列表中选择棕色,并且数据库中已经为棕色保存了一些初始值,则 useEffect 挂钩会更新描述状态,但是,它不会反映在 Tiptap 编辑器内容中。

小智 8

检查这是否有帮助:将描述变量添加到 useEditor 的依赖数组

 const editor = useEditor({
    ...
 },[description]);
Run Code Online (Sandbox Code Playgroud)


jac*_*her 5

您可能希望在编辑器组件内运行效果以使用setContent上面评论中引用的函数。

这看起来像

  const editor = useEditor({
    ...
  });

  useEffect(() => {
    editor.commands.setContent(description);
  }, [description]);
Run Code Online (Sandbox Code Playgroud)

通过添加为依赖项来重新渲染编辑器description可能有效,但 1) 更昂贵,2) 可能不会完全按照您想要的方式显示,3) 不会触发onTransaction或您可能依赖的任何 TipTap 回调或状态更改将来。