Gatsby 基于redux状态的Youtube组件的条件呈现(cookie接受)

Gatsby 基于redux状态的Youtube组件的条件呈现(cookie接受),gatsby,Gatsby,在我的盖茨比网站上,我想要一个Youtube组件,因为GDPR,它只在用户接受cookies时才会出现。如果他们拒绝了cookie,我希望它能为重置他们的首选项提供指导,如果cookie接受状态未知(比如说他们使用的扩展阻止了cookie通知),我希望它能说它不知道cookie是否被允许,如果你没有看到横幅,请检查你的adblocker 我已经通过react-redux设置了全局状态,检查“acceptCookies”cookie和所有用于显示横幅的逻辑等(都是使用react-cookie同意完

在我的盖茨比网站上,我想要一个Youtube组件,因为GDPR,它只在用户接受cookies时才会出现。如果他们拒绝了cookie,我希望它能为重置他们的首选项提供指导,如果cookie接受状态未知(比如说他们使用的扩展阻止了cookie通知),我希望它能说它不知道cookie是否被允许,如果你没有看到横幅,请检查你的adblocker

我已经通过react-redux设置了全局状态,检查“acceptCookies”cookie和所有用于显示横幅的逻辑等(都是使用react-cookie同意完成的),并将state.acceptCookies设置为true。这在不同的页面上都起到了作用,例如,我只希望在接受cookies时显示一个联系人表单

这是我的组件(我将其包含在任何包含Youtube视频的页面中,并将Youtube代码作为道具传递给它):

从“React”导入React
从“react redux”导入{useSelector}
从“react bootstrap”导入{Alert}
从“盖茨比”导入{Link}
const YouTubeVideo=(道具)=>{
const acceptCookies=useSelector(state=>state.acceptCookies)
返回(
{acceptCookies===''&&

我们无法显示此YouTube视频,因为Cookie未被接受,
但YouTube必须具备这些功能才能正常工作。为了遵守GDPR法律
在您接受Cookie之前,不会显示视频。

如果您没有看到cookie横幅,请尝试重置您的 隐私政策的首选项或 禁用任何内容阻止程序。

} {acceptCookies==='false'&& 我们无法显示此YouTube视频,因为cookies已被拒绝,但是 是YouTube正常运行所必需的。为了遵守GDPR法律,视频 不显示。

您可以从中重置您的首选项 隐私政策

} {acceptCookies==='true'&& } ) } 导出默认YouTubeVideo
我尝试过其他语法,比如使用if语句和多个渲染块,没有区别

我试着将它重写为一个类并使用connect(),没有区别

就我个人而言,我无法让它正常工作。它在开发模式下工作正常-初始状态显示“Cookie未被接受”警报,拒绝显示“Cookie已被拒绝”警报,接受显示视频,一切正常。我恢复了精神,一切都在继续

但是一旦我建立并部署了这个站点,它的行为就非常奇怪了。乍一看似乎很好-初始状态显示“Cookie尚未被接受”警报,拒绝显示“Cookie已被拒绝”警报,接受显示视频。然后刷新页面,然后。。。。它显示了一个警报内的视频小版本!(没有警报文本)。真奇怪。就像它遵循“cookies not accepted”(cookies not accepted)逻辑并开始绘制警报,然后在写入段落之前,点击某种竞争条件并呈现代码的“cookies accepted”(cookies accepted)部分,即视频。我一点也不明白,我希望它能呈现三件事中的一件,而不是以某种方式将结果混合在一起

我错过了什么?我完全不知所措。我想我一定是在预渲染时被什么东西绊倒了,但就是想不起来

编辑:头脑更清醒的时候,我想至少尝试将acceptCookies设置为静态“true”,看看问题是在于我的渲染(在这种情况下它仍然无法正确显示)还是全局状态实现(在这种情况下它会),并证明是后者。问题是,我不知道如何在盖茨比中正确地执行cookie权限或全局状态(“缓存”它为全局状态,以便在接受cookie时,输出将更新,而无需刷新页面),并且只能真正地将有关vanilla React和盖茨比的教程混搭在一起。我最好还是重写一下——现在我记不起我用了哪本教程了

不过要补充一点,这就是我所拥有的

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>
}
cookie同意通知是layout.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)
从“反应cookie同意”导入CookieConsent
constourcookieconsent=({acceptCookies,accept,decept})=>(
本网站使用Cookie用于:

  • 必需:保存cookie首选项
  • 可选:“联系我们”页面上的联系表单-用于垃圾邮件 控制(reCAPTCHA)
  • 可选:嵌入YouTube视频,例如新闻页面中的视频
拒绝同意将禁用标记为可选的功能

获取更深入的详细信息或撤销或重新建立您的 任何时候同意,请参阅隐私政策

) OurCookieConsent.propTypes={ acceptCookies:PropTypes.string.isRequired, 接受:PropTypes.func.isRequired, 拒绝:需要PropTypes.func.isRequired, } 常量mapStateToProps=({acceptCookies})=>{ 返回{acceptCookies} } const mapDispatchToProps=调度=>{ 返回{ accept:()=>分派({type:`accept_COOKIES`}), 拒绝:()=>dispatch({type:`declient\u COOKIES`}) } } const ConnectedCookieConsent=connect(mapStateToProps,mapDispatchToProps)(我们的CookieConsent)

然后,布局中包含ConnectedCookieConsent。

我将编写
YoutubeVideo
组件,如下所示:

从“React”导入React
从“react redux”导入{useSelector}
导入{Alert}
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)
import React from "react"
import { connect } from "react-redux"
import { Alert } from "react-bootstrap"
import { Link } from "gatsby"

function mapStateToProps(state) {
  return { acceptCookies: state.acceptCookies }
}

class YouTubeVideo extends React.Component {
  state = {
    acceptCookies: 'undecided',
  }

  componentDidMount() {
    this.setState({
      acceptCookies: this.props.acceptCookies,
    })
  }

  componentDidUpdate() {
    if (this.state.acceptCookies !== this.props.acceptCookies) {
      this.setState({
        acceptCookies: this.props.acceptCookies,
      })
    }
  }

  render () {
    const { acceptCookies } = this.state
    if (acceptCookies === 'undecided') {
      return (
          <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>
      )
    }
    if (acceptCookies === 'false') {
      return(
          <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>
      )
    }

    if (acceptCookies === 'true') {
      return (
          <div className="embed-container">
            <iframe src={`https://www.youtube.com/embed/${this.props.code}?rel=0`}
              title={`YouTube Video ${this.props.code}`}
              frameBorder="0"
              allowFullScreen
            >
            </iframe>
          </div>
      )
    }
    return (
      <p><a href={`https://www.youtube.com/watch?v=${this.props.code}`}>YouTube Video</a></p>
    )
  }
}


export default connect(mapStateToProps)(YouTubeVideo)