cookieconsent: Bug: plugin is executed twice inside the `useEffect` hook in React

Version 3.0.0-rc.5

What is the correct way to use the API?

The way I do it is import it like shown in the docs: import * as CookieConsent from 'vanilla-cookieconsent';

Then I try to call either CookieConsent.acceptCategory('analytics') or CookieConsent.acceptService('ga', 'analytics') on button click. The cookie gets added, its timestamp is updated, but “categories” and “services” arrays are empty.

Setting categories and services via the modal works fine.

Also, when accessing imported CookieConsent, typescript complains: “Cannot use namespace ‘CookieConsent’ as a value.” I have to cast it as CookieConsent.CookieConsentAPI for typescript to stop complaining.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 20 (4 by maintainers)

Commits related to this issue

Most upvoted comments

s, it seems that v3.0 is required to get it to work properly.

Not really. React 18 made things just a little more “complicated”, especially for iife + client only plugins such cookieconsent v2.

@itsam, this is the easiest way to use v2 in next.js (call api via the window object): https://stackblitz.com/edit/nextjs-euxk9k?file=components%2FCookieConsentComponent.js

I’ll update the FAQ -> How to use in React section for future users.

I use the API this way with Next.js:

import { useEffect, createContext, useContext } from "react"
import "vanilla-cookieconsent/dist/cookieconsent.js"
import "vanilla-cookieconsent/dist/cookieconsent.css"

const CookieContext = createContext();

const CookieConsentProvider = ({ children, locale }) => {
  const cc = window.initCookieConsent();
  useEffect(() => {
    cc.run({
       autorun: true,
       current_lang: locale,
       autoclear_cookies: true,
       page_scripts: true,
       // your config goes here
    });
  }, [locale]);

    return (
        <CookieContext.Provider value={{ cc }}>
            {children}
        </CookieContext.Provider>
    );
}

export default CookieConsentProvider

export function useCookieConsent() {
    const context = useContext(CookieContext);
    if (context === undefined) {
      throw new Error('Context must be used within a Provider');
    }
    return context;
}

Then in my page component:

const CookieConsentProvider = dynamic(() => import('components/CookieConsentProvider'), {
  ssr: false,
})

export default function Page() {
return (
    <CookieConsentProvider locale={locale}>
       <Layout>
         ...
       </Layout>
    </CookieConsentProvider>
  )
}

Then in any child component I can do the following:

import { useCookieConsent } from 'components/CookieConsentProvider'

const MyComponent = () => {
   const { cc } = useCookieConsent()

  const handleClick = () => {
     cc.accept('marketing')
  }
}

s, it seems that v3.0 is required to get it to work properly.

Not really. React 18 made things just a little more “complicated”, especially for iife + client only plugins such cookieconsent v2.

@itsam, this is the easiest way to use v2 in next.js (call api via the window object): https://stackblitz.com/edit/nextjs-euxk9k?file=components%2FCookieConsentComponent.js

I’ll update the FAQ -> How to use in React section for future users.

You are, right, in the proposed solution, everything works as expected in stable release 2.8.6. I think the tricky part (besides limiting to load just once in the useEffect) was to use window (e.g. window.CookieConsentApi.showSettings(0)) all the times instead of the object (e.g. cc) which either created once in the context, zustand or wherever.

Thanks a lot for clarifying and giving a functional example, I am pretty sure it will be helpful for others trying to integrate with next.js

Released v3.0.0-rc.6, feel free to re-open this issue if you still encounter the problem.

@Polynook

that is indeed the proper way to use the plugin.

I believe this issue is caused by React’s new useEffect behaviour; the useEffect hook is executed twice in dev/strict mode and messes up the plugin.

As for the types issue, it has already been fixed in the v3 branch https://github.com/orestbida/cookieconsent/commit/93ccc795406f9c42528d22c8a17da890d2857f30.

Note: you could also use named imports

import { run, acceptCategory } from 'vanilla-cookieconsent'