kavandalal
kavandalal

Reputation: 124

Correct way to use forwardRef and next/dynamic in next.js 13.4 for "react-email-editor"

I have been trying to use "react-email-editor" in next. I want to copy the email content that was made in the editor to clipboard. As the package uses "window" for interaction, I was trying to use next/dynamic to disable ssr. So I tried creating a different component for EmailEditor. But when I tried to log the emailEditorRef it was never pointing to the EmailEditor. I need the emailEditorRef to copy the content in the EmailEditor.

The version I was using are: "react": "18.2.0", "next": "13.4.19" , "react-email-editor": "^1.7.9".

I divided the main logic into 3 files: page.tsx, types.tsx, email-ui.tsx.

page.tsx

'use client';

import { Button } from '@/components/ui/button';
import { toast } from '@/components/ui/use-toast';
import React, { useEffect, useRef } from 'react';
import { EditorRef, EmailEditorProps } from '@/components/email-template/types';
import ForwardedEmailEditor from '@/components/email-template/email-ui';

export default function Page() {
    const emailEditorRef = useRef<EditorRef | null>(null);

    useEffect(() => {
        console.log('ref changed = ', emailEditorRef.current);
    }, [emailEditorRef]);

    const exportHtml = () => {
        const unlayer = emailEditorRef.current?.editor;
        unlayer?.exportHtml((data) => {
            const { design, html } = data;
            try {
                console.log('Copy function Running',html);
                navigator.clipboard.writeText(html);
            } catch (error) {
                console.error('Clipboard write failed:', error);
            }
        });
    };

    const onReady: EmailEditorProps['onReady'] = (unlayer) => {
        console.log('editor react-email-editor is ready', emailEditorRef.current);
    };

    return (
        <section >
            <div>
                <span>Create Email Template</span>
                <Button onClick={exportHtml}>Export HTML</Button>
            </div>
            <div>
                <ForwardedEmailEditor ref={emailEditorRef} onReady={onReady} />
            </div>
        </section>
    );
}`

email-ui.tsx

'use client';

import React from 'react';
import dynamic from 'next/dynamic';
import { EmailEditorProps, EditorRef } from './types';

const DynamicEmailEditor = dynamic(() => import('react-email-editor'), { ssr: false });

const ForwardedEmailEditor = React.forwardRef<EditorRef, EmailEditorProps>((props, ref) => {
    return <DynamicEmailEditor ref={ref} {...props} />;
});

export default ForwardedEmailEditor;

types.tsx

'use client';

export type { EditorRef, EmailEditorProps } from 'react-email-editor';

Upvotes: 1

Views: 878

Answers (2)

kavandalal
kavandalal

Reputation: 124

I found the value unlayer in the params of onReady function is a editor type, so I used that and changed the value of emailEditorRef.current to point to the editor.

page.tsx

...
    const onReady: EmailEditorProps['onReady'] = (unlayer) => {
        emailEditorRef.current = { editor: unlayer };
    };
...

and removed the unnecessary code from email-ui.tsx page as the default export of EmailEditor was React.ForwardRefExoticComponent

email-ui.tsx

'use client';

import dynamic from 'next/dynamic';

const DynamicEmailEditor = dynamic(() => import('react-email-editor'), { ssr: false });

export default DynamicEmailEditor;

Upvotes: 1

Anh Tran
Anh Tran

Reputation: 234

The exported EmailEditor is declared as React.ForwardRefExoticComponent, so you don't need to wrap it in a forwardRef function. Just export default DynamicEmailEditor

enter image description here

Upvotes: 0

Related Questions