unlayer / react-email-editor

Drag-n-Drop Email Editor Component for React.js
https://unlayer.com/embed
MIT License
4.51k stars 728 forks source link

Next js Could not find a valid element for given id or className. #411

Open samanch8 opened 1 month ago

samanch8 commented 1 month ago

Unhandled Runtime Error Error: Could not find a valid element for given id or className. this error occues in next js 14

RitikR307 commented 1 month ago

I am facing the similiar issue in react-navtice codebase Here is the code snippet

import React, { useEffect, useRef, useState } from 'react';
import { render } from 'react-dom';
import {
    VStack,
    Button,
    ButtonText,
    Modal,
    ModalBackdrop,
    ModalContent,
    ModalHeader,
    Heading,
    ModalCloseButton,
    ModalBody,
    ModalFooter,
    Input,
    InputField
} from '@gluestack-ui/themed';
import EmailEditor, { EditorRef, EmailEditorProps } from 'react-email-editor';
import { sendEmail } from '../../components/EmailSenderHelper';
import { addTemplate } from '../../api';

const EmailEditorWindow = ({ isEmailEditorOpen, onClose, loggedInUserData, selectedChatInfo, chatInfo, navigation, route, }) => {

    const loggedInUserEmail = loggedInUserData.uid;
    const [showEmailEditorModal, setShowEmailEditorModal] = useState(isEmailEditorOpen);
    const [showTemplateModal, setShowTemplateModal] = useState(false);
    const [chatParticipantsEmail, setChatParticipantsEmail] = useState([]);
    const [templateName, setTemplateName] = useState('');
    const [isButtonDisabled, setIsButtonDisabled] = useState(true);
    const emailEditorRef = useRef(null);

    useEffect(() => {

    }, [templateName])
    useEffect(() => {
        const users = selectedChatInfo?.meta?.users;
        const userEmailIds = [];
        for (let key in users) {

            users[key]?.uid && users[key]?.uid !== loggedInUserEmail && userEmailIds.push(users[key]?.uid);
        }
        setChatParticipantsEmail(userEmailIds);
    }, []);

    useEffect(() => {

    }, [chatParticipantsEmail]);

    useEffect(() => {

        setShowEmailEditorModal(isEmailEditorOpen);
    }, [isEmailEditorOpen]);

    const sendData = async () => {
        const unlayer = emailEditorRef.current?.editor;
        unlayer?.exportHtml(async (data) => {
            const { design, html } = data;
            console.log('exportHtml', html);
            await sendEmail({
                message: html,
                sendMessageNowFlag: true,
                subject: 'template'
            }, selectedChatInfo, loggedInUserData);
            setShowEmailEditorModal(false);
        });
    };

    const customJS = () => {
        window.unlayer.registerTool({
            name: 'customButton',
            label: 'Custom Button',
            icon: 'fa-hand-pointer', // Use an appropriate icon
            supportedDisplayModes: ['web', 'email'],
            options: {
                default: {
                    link: {
                        value: '',
                        label: 'Button Link',
                        widget: 'text'
                    }
                }
            },
            toolbox: {
                title: 'Custom Button',
                icon: 'fa-hand-pointer'
            },
            properties: {
                link: {
                    label: 'Button Link',
                    widget: 'text'
                }
            },
            render: function (block) {
                return `<div  style="text-align:center;padding:10px;">
                            <a " style="padding: 10px 20px; background-color: #007bff; color: #ffffff; text-decoration: none;">Click me</a>
                        </div>`;
            }
        });
    };
    const onReady = (unlayer) => {
        setIsButtonDisabled(false);
        unlayer.init({
            id: 'editor-container',
            displayMode: 'email',
            customJS: ['https://examples.unlayer.com/examples/custom-js/custom.js'],
        });
    };

    const saveTemplate = async () => {
        const unlayer = emailEditorRef.current?.editor;
        unlayer?.exportHtml(async (data) => {
            const { design, html } = data;
            const templateData = {
                name: templateName,
                subject: '',
                body: html,
                templateType: 'html',
            };
            await addTemplate(templateData);
            setShowEmailEditorModal(false);
            onClose();
        });
    };
    const onLoad = () => {

    };
    return (
        <>
            <Modal
                isOpen={showEmailEditorModal}
                size='full'
                onClose={() => {
                    setShowEmailEditorModal(false);
                }}
            >
                <ModalBackdrop />
                <ModalContent>
                    <ModalHeader>
                        <Heading size="lg">Email Editor</Heading>
                        <ModalCloseButton />
                    </ModalHeader>
                    <ModalBody>
                        <VStack>
                            <Button
                                isDisabled={isButtonDisabled}
                                size='md'
                                variant="solid"
                                mr="$3"
                                mb='$3'
                                bgColor='#7A5BF7'
                                onPress={() => {
                                    sendData();
                                }}
                            >
                                <ButtonText>Send Email Template</ButtonText>
                            </Button>
                            <EmailEditor ref={emailEditorRef} onReady={onReady} />
                        </VStack>
                    </ModalBody>
                    <ModalFooter>
                        <Button
                            variant="outline"
                            size="sm"
                            action="secondary"
                            mr="$3"
                            onPress={() => {
                                setShowEmailEditorModal(false);
                                onClose();
                            }}
                        >
                            <ButtonText>Cancel</ButtonText>
                        </Button>
                        <Button
                            isDisabled={isButtonDisabled}
                            variant="solid"
                            size="sm"
                            bgColor='green'
                            mr="$3"
                            onPress={() => {
                                setShowTemplateModal(true);
                            }}
                        >
                            <ButtonText>Save Template</ButtonText>
                        </Button>
                    </ModalFooter>
                </ModalContent>
            </Modal>
            <Modal
                isOpen={showTemplateModal}
                size='sm'
                onClose={() => {
                    setShowTemplateModal(false);
                }}
            >
                <ModalBackdrop />
                <ModalContent>
                    <ModalHeader>
                        <Heading size="lg">Template Info.</Heading>
                        <ModalCloseButton />
                    </ModalHeader>
                    <ModalBody>
                        <Input
                            variant="outline"
                            size="md"
                            placeholder="Enter Template name"
                        >
                            <InputField
                                onChangeText={e => {
                                    console.log('===e:', e);
                                    setTemplateName(e);
                                }}
                                placeholder="Enter Template name" />
                        </Input>
                    </ModalBody>
                    <ModalFooter>
                        <Button
                            variant="solid"
                            size="sm"
                            bgColor='blue'
                            mr="$3"
                            onPress={() => {
                                saveTemplate();
                            }}
                        >
                            <ButtonText>Save</ButtonText>
                        </Button>
                    </ModalFooter>
                </ModalContent>
            </Modal>
        </>
    );
};

export default EmailEditorWindow;

image

vinyoda197 commented 1 month ago

Don't forget to add the container element <div id="editor-container"></div> somewhere in your ui codes