use-cookie-consent icon indicating copy to clipboard operation
use-cookie-consent copied to clipboard

Add a cookie-consent-provider

Open pixelass opened this issue 4 years ago • 8 comments
trafficstars

Is your feature request related to a problem? Please describe.

Feature: Cookie Consent Provider

As a Developer, I want to use a context, so that my application has global access to the consent state

Describe the solution you'd like

Add a CookieConsentProvider (react-context).

Describe alternatives you've considered

I made my own Provider/Context.

Feel free to reuse my code as is. It nicely extends your existing API and adds a new hook useCookieConsentProvider.

I could open a PR for this, but probably not any time soon, since I am currently fully stuffed with work.

Example: https://codesandbox.io/s/eager-tree-by1dk Demo: https://by1dk.csb.app/

import React, { createContext, FC, useContext, useMemo } from "react";
import { CookieConsentHookState, useCookieConsent } from "use-cookie-consent";

export const CookieConsentContext = createContext<CookieConsentHookState>({
	consent: {},
	acceptCookies() {
		/**/
	},
	declineAllCookies() {
		/**/
	},
	acceptAllCookies() {
		/**/
	},
	didAcceptAll() {
		return false;
	},
	didDeclineAll() {
		return false;
	},
	cookies: {
		set() {
			return undefined;
		},
		get() {
			return "";
		},
		getAll() {
			return {};
		},
		getJSON() {
			/**/
		},
		getAllJSON() {
			return {};
		},
		remove() {
			/**/
		},
	},
});

export const CookieConsentProvider: FC = ({ children }) => {
	const {
		consent,
		acceptAllCookies,
		declineAllCookies,
		acceptCookies,
		didAcceptAll,
		didDeclineAll,
		cookies,
	} = useCookieConsent();

	const context = useMemo(
		() => ({
			consent,
			acceptAllCookies,
			declineAllCookies,
			acceptCookies,
			didAcceptAll,
			didDeclineAll,
			cookies,
		}),
		[
			consent,
			acceptAllCookies,
			declineAllCookies,
			acceptCookies,
			didAcceptAll,
			didDeclineAll,
			cookies,
		]
	);

	return (
		<CookieConsentContext.Provider value={context}>{children}</CookieConsentContext.Provider>
	);
};

export const useCookieConsentContext = () => useContext(CookieConsentContext);

Additional context I use the provider like this

import React from "react";
import {useCookieConsentContext, CookieConsentProvider} from "./CookieConsent";

export const CookieBanner = () => {
  const {acceptAllCookies, declineAllCookies, acceptCookies} = useCookieConsentContext();

  return (
    <div>
      <button onClick={acceptAllCookies}>Accept all</button>
      <button onClick={() => acceptCookies({thirdParty: true})}>
        Accept third-party
      </button>
      <button onClick={() => acceptCookies({firstParty: true})}>
        Accept first-party
      </button>
      <button onClick={declineAllCookies}>Reject all</button>
    </div>
  );
};

export const Cookies = () => {
  const {consent} = useCookieConsentContext();

  return (
    <div>
      <div>
        {`Third-party cookies ${consent.thirdParty ? 'approved' : 'rejected'}`}
      </div>
      <div>
        {`First-party cookies ${consent.firstParty ? 'approved' : 'rejected'}`}
      </div>

    </div>
  );
};

export default function App() {
  return (

      <CookieConsentProvider>
        <CookieBanner/>
        <Cookies/>
      </CookieConsentProvider>
  );
}

pixelass avatar Aug 21 '21 07:08 pixelass

I would argue that the use of context is unnecessary. The state is stored in cookies (as "necessary" cookies) and you can use useCookieConsent hook from anywhere and it will use the same consent state from any place in your app.

One reason I see why to use context is to have multiple cookie consent "stores", but not sure if that's needed since you usually have just one cookie consent dialog. I'd love to be proved wrong though 😄

bring-shrubbery avatar Sep 01 '21 08:09 bring-shrubbery

@pixelass Any argument against the one I presented?

bring-shrubbery avatar Sep 14 '21 10:09 bring-shrubbery

@bring-shrubbery I had several issues without a context (not 100% sure which) but I might have just been thinking too complicated. AFAIK I wasn't getting the correct state when using the hook in different components/level of the application we're building. ATM I'm very busy and we currently have a different focus but I will report back when I have time to look into refactoring this.

Edit: If I remember correctly the issue was that when adjusting the consent from one component, then the other component would not be informed since only the cookie itself was adjusted but the hook doesn't listen to changes of the cookies.

pixelass avatar Sep 14 '21 11:09 pixelass

@pixelass Oh yes, that's definitely something we want to have then. I haven't had much time myself, so couldn't look into it properly. I'm happy to either implement your suggested solution myself, or you could send a PR? Both options work for me, just tell me your preference.

I would also add a way of creating your own context instead of having the creation of the context under the hood. That way you could create multiple contexts and prefix the cookies with different prefixes so they don't affect each other.

bring-shrubbery avatar Oct 02 '21 11:10 bring-shrubbery

@pixelass This actually might be something for a separate package. Maybe I should create a @use-cookie-consent organization and publish these as scoped packages. Since this package right now is not really using anything that is React related, it could be used as a core package for other packages that are library-specific (@use-cookie-consent/react, @use-cookie-consent/vue, etc)

bring-shrubbery avatar Oct 02 '21 12:10 bring-shrubbery

@pixelass I just did that actually 😅 Feel free to add the code for the consent provider to this repo, otherwise I'll put it there in a couple of days 🙂

bring-shrubbery avatar Oct 03 '21 07:10 bring-shrubbery

@pixelass The use-cookie-consent-react package now exists and I left the source code empty specifically if you want to add this functionality yourself. You can find it here. If you won't add it this weekend I'll add it myself and try to mark you as an author of that commit 😇

bring-shrubbery avatar Oct 08 '21 05:10 bring-shrubbery

@bring-shrubbery Thank you. Sadly I won't have time to look into it anytime soon. Feel free to use my code without credit. If I have time I'll be happy to contribute.

pixelass avatar Oct 08 '21 06:10 pixelass