Skip to content

Instantly share code, notes, and snippets.

@daankauwenberg
Created February 25, 2020 12:04
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save daankauwenberg/bf0daf4d4a9a157a078ba4ec4559e3ab to your computer and use it in GitHub Desktop.
Save daankauwenberg/bf0daf4d4a9a157a078ba4ec4559e3ab to your computer and use it in GitHub Desktop.
A React cookie consent using hooks and context
import React from 'react';
import { CookieConsentProvider } from './CookieConsent'
import Page from './Page'
function App() {
return (
<CookieConsentProvider>
<div className="App">
<Page />
</div>
</CookieConsentProvider>
);
}
export default App;
import React, { createContext, useReducer, useEffect, useState, useContext } from 'react'
import CookiePopup from './CookiePopup'
const COOKIE_NAME = 'consent'
const CookieConsentStateContext = createContext()
const CookieConsentDispatchContext = createContext()
function getCookie() {
const regex = new RegExp(`(?:(?:^|.*;\\s*)${COOKIE_NAME}\\s*\\=\\s*([^;]*).*$)|^.*$`)
const cookie = document.cookie.replace(regex, "$1")
return cookie.length ? JSON.parse(cookie) : undefined
}
// Initial value is cookie value OR prefered value but not yet set
let initialCookieValue = getCookie() || {
isSet: 0,
marketing: 1
}
const CookieConsentProvider = ({ children }) => {
const [popupIsOpen, setPopupIsOpen] = useState(!initialCookieValue.isSet)
const [state, dispatch] = useReducer((state, action) => {
switch (action.type) {
case 'acceptCurrent':
setPopupIsOpen(false)
return {
...state,
isSet: 1,
}
case 'declineAll':
setPopupIsOpen(false)
return {
isSet: 1,
marketing: 0,
}
case 'showCookiePopup':
setPopupIsOpen(true)
return state
default:
throw new Error()
}
}, initialCookieValue)
// Update the cookie when state changes
useEffect(() => {
document.cookie = `${COOKIE_NAME}=${JSON.stringify(state)}`
}, [state])
return (
<CookieConsentStateContext.Provider value={state}>
<CookieConsentDispatchContext.Provider value={dispatch}>
{popupIsOpen && <CookiePopup dispatch={dispatch} />}
{children}
</CookieConsentDispatchContext.Provider>
</CookieConsentStateContext.Provider>
)
}
function useCookieConsentState() {
const context = useContext(CookieConsentStateContext)
if (context === undefined) {
throw new Error('useCookieConsentState must be used within CookieProvider')
}
return context
}
function useCookieConsentDispatch() {
const context = useContext(CookieConsentDispatchContext)
if (context === undefined) {
throw new Error('useCookieConsentDispatch must be used within CookieProvider')
}
return context
}
export { CookieConsentProvider, useCookieConsentState, useCookieConsentDispatch }
import React from 'react'
const CookiePopup = ({dispatch}) => (
<section>
<p>We use cookies!</p>
<button onClick={() => dispatch({type: 'acceptCurrent'})}>Accept</button>
<button onClick={() => dispatch({type: 'declineAll'})}>Decline</button>
</section>
)
export default CookiePopup
import React from 'react'
import { useCookieConsentState, useCookieConsentDispatch } from './CookieConsent'
const Page = () => {
const cookieConsentState = useCookieConsentState()
const cookieConsentDispatch = useCookieConsentDispatch()
return (
<article>
<h1>Title</h1>
<button onClick={() => cookieConsentDispatch({type: 'showCookiePopup '})}>Update cookie settings</button>
{cookieConsentState.isSet && cookieConsentState.marketing ?
<script>
{/* Marketing code here */}
</script>
: ''}
</article>
)
}
export default Page
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment