I'm using TipTap as the rich text editor for my react project for updating the description of the product which has been selected from the dropdown.
The expected outcome is that the editor should show the initial content which has been saved in the database for the respective product.
However, using the 'content' option in editor allows me to set the initial content, it does not updates the initial content if i change the option in dropdown.

My Editor Code:
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;
This Editor component is then called in a parent component to display the data:
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;
What I am trying to achieve:
If a user selects the color brown in dropdown and there is already some initial value saved for the same in database for brown, then the useEffect hook updates the description state, however, it is not reflected in the tiptap editor content.
Check if this helps: add description variable to dependency array of useEditor
const editor = useEditor({
...
},[description]);
You'll probably want to run the effect inside of the Editor component to use the setContent function referenced in a comment above.
This would look something like
const editor = useEditor({
...
});
useEffect(() => {
editor.commands.setContent(description);
}, [description]);
Re-rendering the editor by adding description as a dependency may work but is 1) more expensive, 2) may not appear precisely as you'd like and 3) doesn't trigger onTransaction or any of TipTap's callbacks or state changes that you may depend on in the future.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With