На моем сайте Gatsby я хочу, чтобы компонент Youtube появлялся только в том случае, если пользователь принял файлы cookie из-за GDPR. Если они отклонили файлы cookie, я хочу, чтобы он дал руководство по сбросу их настроек, и если состояние принятия cook ie неизвестно (скажем, они используют расширение, которое заблокировало уведомление cook ie), я хочу, чтобы он сказал, что он не знает, разрешены ли файлы cookie или нет, и если вы не видите баннер, проверьте свой блокировщик рекламы.
Я уже настроил глобальное состояние с помощью response-redux, который проверяет 'acceptCookies' cook ie и все logi c для отображения баннера et c (все это делается с помощью response-cook ie -consent) и устанавливает для state.acceptCookies значение true. Это работало на различных страницах, где, например, я хочу, чтобы контактная форма отображалась только в том случае, если принимаются файлы cookie.
Это мой компонент (который я включаю на любую страницу, которая должна иметь видео Youtube, передавая его код Youtube в качестве опоры):
import React from "react"
import { useSelector } from "react-redux"
import { Alert } from "react-bootstrap"
import { Link } from "gatsby"
const YouTubeVideo = (props) => {
const acceptCookies = useSelector(state => state.acceptCookies)
return (
<>
{acceptCookies === '' &&
<Alert variant="warning">
<p>
We cannot show this YouTube video as cookies have not been accepted,
but are required for YouTube to work. To comply with GDPR law, the
video is not displayed until you have accepted cookies.
</p>
<p>
If you do not see the cookie banner, please try resetting your
preferences from the <Link to="/privacy-policy">Privacy Policy</Link> or
disabling any content blockers.
</p>
</Alert>
}
{acceptCookies === 'false' &&
<Alert variant="warning">
<p>
We cannot show this YouTube video as cookies have been declined, but
are required for YouTube to work. To comply with GDPR law, the video
is not displayed.
</p>
<p>
You may reset your preferences from
the <Link to="/privacy-policy">Privacy Policy</Link>
</p>
</Alert>
}
{acceptCookies === 'true' &&
<div className="embed-container">
<iframe src={`https://www.youtube.com/embed/${props.code}?rel=0`}
title={`YouTube Video ${props.code}`}
frameBorder="0"
allowFullScreen
>
</iframe>
</div>
}
</>
)
}
export default YouTubeVideo
Я пробовал другой синтаксис, такой как использование операторов if и нескольких блоков рендеринга, без разницы
Я пробовал переписать его как класс и используя connect (), никакой разницы
Да хоть убей, я не могу заставить его работать должным образом. Он отлично работает в режиме разработки - в исходном состоянии отображается предупреждение «файлы cookie не приняты», при отклонении отображается предупреждение «файлы cookie отклонены», а при принятии отображается видео, и все в порядке. Я обновляю sh, и все продолжает работать.
Но как только я создаю и развертываю сайт, он ведет себя очень странно. Сначала это кажется нормальным - начальное состояние показывает предупреждение «куки не были приняты», отклонение показывает предупреждение «куки были отклонены», а принятие показывает видео. А затем вы обновляете sh страницу и .... внутри предупреждения отображается небольшая версия видео! (Без текста предупреждения). Это действительно странно. Это похоже на то, как если бы он следовал логике «куки не приняты» logi c и начинал рисовать предупреждение, а затем, прежде чем писать в абзацах, достигал какого-то состояния гонки и рендерил часть кода «куки приняты», то есть видео. Я вообще не понимаю, я бы ожидал, что он отобразит одну из трех вещей, а не как-то sh результаты вместе.
Что мне здесь не хватает? Я совершенно сбит с толку. Я думаю, что я, должно быть, споткнулся о что-то при предварительном рендеринге, но просто не могу понять это.
Edit: с более ясной головой я подумал хотя бы попробовать установить acceptCookies на stati c 'true', чтобы увидеть, связана ли проблема с моим рендерингом (в этом случае он все равно будет отображаться некорректно) или реализацией глобального состояния (в этом случае будет), и доказал, что это последнее. На самом деле проблема в том, что я не знаю, как правильно сделать ie разрешение или глобальное состояние в Gatsby («кэшировать» его как глобальное состояние, чтобы после принятия файлов cookie вывод обновлялся без необходимости обновлять sh page) и мог только go из ma sh руководств по vanilla React и Gatsby. Мне, вероятно, лучше всего его переписать - на данный момент я не могу вспомнить, какие учебники я использовал!
Однако, чтобы добавить, это то, что у меня есть
gatsby-ssr. js и gatsby-browser. js оба содержат:
import wrapWithProvider from "./wrap-with-provider"
export const wrapRootElement = wrapWithProvider
wrap-with-provider. js:
import React from "react"
import { Provider } from "react-redux"
import createStore from "./src/state/createStore"
// eslint-disable-next-line react/display-name,react/prop-types
export default ({ element }) => {
// Instantiating store in `wrapRootElement` handler ensures:
// - there is fresh store for each SSR page
// - it will be called only once in browser, when React mounts
const store = createStore()
return <Provider store={store}>{element}</Provider>
}
src / state / createStore. js:
import { createStore as reduxCreateStore } from "redux"
import Cookies from 'js-cookie'
const reducer = (state, action) => {
if (action.type === `ACCEPT_COOKIES`) {
return Object.assign({}, state, {
acceptCookies: 'true',
})
}
if (action.type === `DECLINE_COOKIES`) {
return Object.assign({}, state, {
acceptCookies: 'false',
})
}
if (action.type === `RESET_COOKIES`) {
return Object.assign({}, state, {
acceptCookies: '',
})
}
return state
}
const initialState = { acceptCookies: Cookies.get('acceptCookies') || '' }
const createStore = () => reduxCreateStore(reducer, initialState)
export default createStore
Повар ie уведомление о согласии является частью макета. js так, чтобы оно было на каждой странице всякий раз, когда это необходимо:
import CookieConsent from "react-cookie-consent"
const OurCookieConsent = ({ acceptCookies, accept, decline }) => (
<CookieConsent
location="bottom"
enableDeclineButton={true}
cookieName="acceptCookies"
onDecline={decline}
onAccept={accept}
>
<p>This website uses cookies for:</p>
<ul>
<li>REQUIRED: Saving your cookie preferences</li>
<li>OPTIONAL: The contact form on the "Contact Us" page - for spam
control (reCAPTCHA).</li>
<li>OPTIONAL: Embedded YouTube videos e.g. videos in our news pages
</li>
</ul>
<p>Declining consent will disable the features marked as OPTIONAL.</p>
<p>For more in-depth detail or to withdraw or re-establish your
consent at any time, please see the <Link to="/privacy-policy">Privacy Policy</Link>.</p>
</CookieConsent>
)
OurCookieConsent.propTypes = {
acceptCookies: PropTypes.string.isRequired,
accept: PropTypes.func.isRequired,
decline: PropTypes.func.isRequired,
}
const mapStateToProps = ({ acceptCookies }) => {
return { acceptCookies }
}
const mapDispatchToProps = dispatch => {
return {
accept: () => dispatch({ type: `ACCEPT_COOKIES` }),
decline: () => dispatch({ type: `DECLINE_COOKIES` })
}
}
const ConnectedCookieConsent = connect(mapStateToProps, mapDispatchToProps)(OurCookieConsent)
Тогда ConnectedCookieConsent включается внутрь макет.