I’m trying to integrate react-draft-wysiwyg rich text editor into my next.js project, but I’m having problems with the dropdowns for font, font size, and block type. I don’t know what the problem is or how to fix this in next.js. There’s only so much information online that can help me figure this out. Here’s the code:
'use client';
import React, { useState, useEffect, useRef } from 'react';
import { useSearchParams } from 'next/navigation';
import dynamic from 'next/dynamic';
import { EditorState, convertFromRaw, convertToRaw } from 'draft-js';
import { firestore } from '../../firebase';
import { getDoc, doc, updateDoc } from 'firebase/firestore';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
const Editor = dynamic(() => import('react-draft-wysiwyg').then(mod => mod.Editor), {
ssr: false
});
interface Document {
id: string;
title: string;
content: string;
createdAt: Date;
}
const DocumentPage: React.FC = () => {
const params = useSearchParams();
const id = params.get("id");
const [document, setDocument] = useState<Document | null>(null);
const [editorState, setEditorState] = useState(() => EditorState.createEmpty());
const isMounted = useRef(true); // Track mounted state
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);
useEffect(() => {
const fetchDocument = async () => {
if (id) {
try {
const docRef = await getDoc(doc(firestore, `documents/${id}`));
if (docRef.exists()) {
const docData = docRef.data() as Document;
if (isMounted.current) {
setDocument(docData);
if (docData.content) {
try {
const contentState = convertFromRaw(JSON.parse(docData.content));
const initialEditorState = EditorState.createWithContent(contentState);
setEditorState(initialEditorState);
} catch (error) {
console.error('Error parsing content:', error);
}
} else {
console.warn('Document content is empty or undefined');
}
}
} else {
console.error('Document not found');
}
} catch (error) {
console.error('Error fetching document: ', error);
}
}
};
fetchDocument();
}, [id]);
const handleEditorChange = (newEditorState: EditorState) => {
setEditorState(newEditorState);
};
const saveDocument = async () => {
if (!document || !editorState) return;
try {
const contentState = editorState.getCurrentContent();
const rawContentState = convertToRaw(contentState);
await updateDoc(doc(firestore, `documents/${id}`), {
content: JSON.stringify(rawContentState)
});
console.log('Document saved successfully');
} catch (error) {
console.error('Error saving document: ', error);
}
};
if (!document) {
return <p>Loading...</p>;
}
return (
<div>
<h1>{document.title}</h1>
<Editor
editorState={editorState}
onEditorStateChange={handleEditorChange}
placeholder="Start typing..."
toolbar={{
options: ['inline', 'blockType', 'fontSize', 'fontFamily', 'list', 'textAlign', 'colorPicker', 'link', 'embedded', 'emoji', 'image', 'remove', 'history'],
inline: { options: ['bold', 'italic', 'underline', 'strikethrough', 'monospace'], inDropdown: false },
blockType: {inDropdown: true, options: ['Normal', 'header-one', 'header-two', 'H3', 'H4', 'H5', 'H6', 'Blockquote', 'Code'] },
fontSize: {inDropdown: true, options: [8, 9, 10, 11, 12, 14, 16, 18, 24, 30, 36, 48, 60, 72, 96] },
fontFamily: {inDropdown: true, options: ['Arial', 'Georgia', 'Impact', 'Tahoma', 'Times New Roman', 'Verdana'] },
list: { inDropdown: false },
textAlign: { inDropdown: false },
link: { inDropdown: false },
history: { inDropdown: false }
}}
/>
<button onClick={saveDocument}>Save Document</button>
</div>
);
};
export default DocumentPage;
I’m working with the app router.