PostHog / posthog-js

Send usage data from your web app or site to PostHog, with autocapture.
https://posthog.com/docs/libraries/js
Other
235 stars 104 forks source link

'dangerouslySetInnerHTML' warning when initializing posthog and next-theme #774

Closed msquinn closed 1 week ago

msquinn commented 11 months ago

When I try to use posthog in addition to next-theme I get an error in the browser saying Warning: PropdangerouslySetInnerHTMLdid not match. I'm using Next 13 app router. It seems as though adding my posthog provider to the layout component strips some attributes related to my theme from my project at build time, which later get applied and loaded client side, causing a mismatch. Here's a code sandbox with the minimal code to reproduce the issue. Note, to actually see the error in the sandbox you'll need to pass in your own API key for Posthog and view the application in it's own browser tab and then check the logs from there.

Screenshot 2023-08-16 at 9 08 36 AM

jaxony commented 6 months ago

Also running into this issue, any fixes?

financialvice commented 4 months ago

bumping this! having the same issue

jakevollkommer commented 4 months ago

same issue here

msquinn commented 4 months ago

So I originally posted my question a few months back. The response from the posthog team was underwhelming. They just told me to leave as is. I actually ended up using a different project called highlight.io for session recording, because I couldn't figure out the proper workaround. It probably exists, though it might just be to suppress the hydration warning.

https://nextjs.org/docs/messages/react-hydration-error

wladpaiva commented 2 months ago

I've narrow it down to the session recordings.

https://github.com/PostHog/posthog-js/assets/1843792/c1d80d03-d462-4d96-a38a-eacd7c16ad66

Everything else seems to be working fine

andlipro commented 1 month ago

Can we init posthog after first render, by useEffect? Works for me:

export default function CSPostHogProvider({ children }: { children: ReactNode }) {
    useEffect(() => {
        if (!posthog.__loaded) {
            posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY || "", { api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST });
        }
    }, []);
    return <PostHogProvider client={posthog}>{children}</PostHogProvider>;
}
stormynight9 commented 1 week ago

Has anybody found a solution for this?

martinamps commented 1 week ago

+1 seeing this in remix with prop mismatches if I add posthog

wladpaiva commented 1 week ago

The solution I've found for this is to create a new org for development only and disable screen recording on PH's dashboard

pauldambra commented 1 week ago

hey all, sorry we missed this!

i'm just investigating to see what I can find out (but I'll admit to not having used SSR or Next JS much so feel free to prompt or correct me!)


I've forked the supplied code sandbox and can replicate the issue whether or not I include posthog

That might only mean I'm confused about the problem :)

If I open the application in incognito mode then I don't get the error

Adding posthog back in using just the JS snippet (and in incognito mode) I don't get the error

And doing the same with the code sandbox in the initial OP I don't get an error in incognito but I do in my normal browser


So I originally posted my question a few months back.

@msquinn sorry you weren't happy with the response... you linked to the nextjs link in your comment so I can't follow up, but I'm happy to look into it 💖

pauldambra commented 1 week ago

So, I'm only getting the error because I have the locator js extension installed

are others able to test if they still get the error in an incognito window or with all browser extensions disabled

(I'm super happy to investigate further but need to be able to consistently repro or i'll just be chasing my tail - and you all will know next/ssr better than me 😊)

pauldambra commented 1 week ago

@wladpaiva toggling session replay didn't change anything for me but then I may just not be replicating the problem correctly)

pauldambra commented 1 week ago

also see https://x.com/martinamps/status/1811491989084577911 https://github.com/martinamps/posthog-repro/tree/main

jakevollkommer commented 1 week ago

We are indeed using radix components, specifically shadcn/ui

pauldambra commented 1 week ago

so looking at the repro provided by martin i get the same error if i don't include posthog

import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode, useEffect } from "react";
import { hydrateRoot } from "react-dom/client";
// import posthog from "posthog-js";

function PosthogInit() {
  // useEffect(() => {
  //   posthog.init('phc_RpO1rh8u4ZgIDxSelv4kQDvyiyyty6iUiLpbs3sTOyb', {
  //     api_host: 'https://us.i.posthog.com',
  //     person_profiles: 'identified_only',
  //   });
  // }, []);

  return null;
}
startTransition(() => {
  hydrateRoot(
    document,
    <StrictMode>
        <RemixBrowser />
        <PosthogInit/>   
    </StrictMode>
  );
});

causes the error

if you comment out <PosthogInit/> then the hydrate error goes away

(i also had to disable two browser extensions that caused a similar error in order to test this)


So, I could still be misunderstanding but still can't repro :)

martinamps commented 1 week ago

Ahh nice catch - thanks for looking. We'll add this to the list of reasons I have largely avoided frontend for the past decade 😂 .... For remix at least, this may simply be a documentation issue.. some googling/testing suggests this is a better implementation -- it works + no warnings:

import * as React from 'react';
import { RemixBrowser } from '@remix-run/react';
import { hydrateRoot } from 'react-dom/client';
import posthog from 'posthog-js';

function hydrate() {
  posthog.init('token', {
    api_host: 'https://us.i.posthog.com',
    person_profiles: 'identified_only',
  });

  React.startTransition(() => {
    hydrateRoot(
      document,
      <React.StrictMode>
        <RemixBrowser />
      </React.StrictMode>,
    );
  });
}

if (window.requestIdleCallback) {
  window.requestIdleCallback(hydrate);
} else {
  window.setTimeout(hydrate, 1);
}

likely could go even simpler and throw the Githubissues.

  • Githubissues is a development platform for aggregating issues.