Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Version 5] - Nextjs SSG/SSR not working due usage of window #575

Closed
omridevk opened this issue Apr 27, 2022 · 20 comments
Closed

[Version 5] - Nextjs SSG/SSR not working due usage of window #575

omridevk opened this issue Apr 27, 2022 · 20 comments
Labels

Comments

@omridevk
Copy link

Window is undefined
emoji-mart/dist/index.js (1102:56)

@omridevk
Copy link
Author

can we disable localStorage?

@EtienneLem
Copy link
Member

That’s most likely a compiler error, I doubt SSR can render custom HTML element which is why I didn’t think the presence of window would be an issue.

can we disable localStorage?

I don’t think that’s necessarily the issue here. The line that Next.js is complaining about is this one

export default class HTMLElement extends window.HTMLElement {

I will make sure everything works with SSR.

@EtienneLem EtienneLem added the v5 label Apr 27, 2022
@omridevk
Copy link
Author

Thank you, I would suggest if possible, until then, update v3 to support React v18

@omridevk
Copy link
Author

I also can't fix it by using useEffect as the usual solution for stuff like that.

@Leandro096
Copy link

I am having the same exact issue.
Snapshot

@EtienneLem
Copy link
Member

Okay, that’s indeed as I thought. You need to defer the loading of the script so that it’s only loaded on the client side (and not the server). You can read more about that here: https://dev.to/swyx/how-to-use-web-components-with-next-js-and-typescript-4gg1

Here’s an example of how to import and use the lib with Next.js:

import { useEffect, useRef } from 'react'
import data from '@emoji-mart/data'

function Picker(props = {}) {
  const ref = useRef()

  useEffect(() => {
    import('emoji-mart').then((EmojiMart) => {
      new EmojiMart.Picker({ ...props, data, ref })
    })
  }, [])

  return <div ref={ref}></div>
}

@maltesa
Copy link

maltesa commented May 2, 2022

Thank you for the solution. It is a bit hard to find though. Maybe it would be worth mentioning it in the readme. I guess many people are using frameworks like nextjs that come with ssr out of the box.

@mfer-mickey
Copy link

i think so

@gabek
Copy link

gabek commented May 9, 2022

With the above solution I'm receiving the error:

TypeError: Cannot read properties of undefined (reading 'version')

Does anybody have any ideas why I might be seeing that?

@amanzrx4
Copy link

Okay, that’s indeed as I thought. You need to defer the loading of the script so that it’s only loaded on the client side (and not the server). You can read more about that here: https://dev.to/swyx/how-to-use-web-components-with-next-js-and-typescript-4gg1

Here’s an example of how to import and use the lib with Next.js:

import { useEffect, useRef } from 'react'
import data from '@emoji-mart/data'

function Picker(props = {}) {
  const ref = useRef()

  useEffect(() => {
    import('emoji-mart').then((EmojiMart) => {
      new EmojiMart.Picker({ ...props, data, ref })
    })
  }, [])

  return <div ref={ref}></div>
}

hi, i tried this i rendered inside my component but it's rendered twice and again and again if the the controlled input in changes.

@everdrone
Copy link

Same problem as @amanzrx4

@gabek
Copy link

gabek commented May 26, 2022

This is all disappointing, as I haven't been able to get it working either. If anybody has any suggestions on an Emoji picker component that supports custom emoji and works out of the box with React+Next please share your suggestions!

@austinbuckler
Copy link

austinbuckler commented May 29, 2022

was able to resolve this using dynamic imports and instantiating the Picker constructor in a ref callback function.

putting the picker in useEffect will trigger the effect twice in development mode when react strict-mode is enabled.

function EmojiPicker() {
    const pickerRef = useRef()
    const moduleRef = useRef()
    const handleDivRef = (divEl) => {
        pickerRef.current = divEl
        if (!moduleRef.current) {
            moduleRef.current = import('emoji-mart').then(m => new m.Picker({ ref: pickerRef, data: emojiData }))
        }
    }

    return <div ref={handleDivRef} />
}

@gabek @everdrone

@s0-david
Copy link

Any update on this?

@thienna
Copy link

thienna commented Jun 18, 2022

any update?

@TusharShahi
Copy link

TusharShahi commented Jun 23, 2022

was able to resolve this using dynamic imports and instantiating the Picker constructor in a ref callback function.

putting the picker in useEffect will trigger the effect twice in development mode when react strict-mode is enabled.

function EmojiPicker() {
    const pickerRef = useRef()
    const moduleRef = useRef()
    const handleDivRef = (divEl) => {
        pickerRef.current = divEl
        if (!moduleRef.current) {
            moduleRef.current = import('emoji-mart').then(m => new m.Picker({ ref: pickerRef, data: emojiData }))
        }
    }

    return <div ref={handleDivRef} />
}

@gabek @everdrone

This works. Thanks a lot. But how do I pass props to handle theme and onClick event as defined in PickerProps?

@aamancio
Copy link

Another possible solution is doing this.

import { useEffect, useRef } from "react";
import data from "@emoji-mart/data";

export const EmojiPicker = (props: any) => {
  const ref = useRef<any>();
  const showEmojis = useRef(true);

  useEffect(() => {
    if (showEmojis.current) {
      showEmojis.current = false;
      import("emoji-mart").then((EmojiMart) => {
        new EmojiMart.Picker({ ...props, data, ref });
      });
    }
  }, [props]);

  return <div ref={ref}></div>;
};

@aamancio
Copy link

aamancio commented Jun 26, 2022

One of the things to be aware it seems that non of the methods is respecting customs styles.

@thiagosullivan
Copy link

Another possible solution is doing this.

import { useEffect, useRef } from "react";
import data from "@emoji-mart/data";

export const EmojiPicker = (props: any) => {
  const ref = useRef<any>();
  const showEmojis = useRef(true);

  useEffect(() => {
    if (showEmojis.current) {
      showEmojis.current = false;
      import("emoji-mart").then((EmojiMart) => {
        new EmojiMart.Picker({ ...props, data, ref });
      });
    }
  }, [props]);

  return <div ref={ref}></div>;
};

Thank for this solution! Works perfectly on my case!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests