繁体   English   中英

在页面入口处仅显示一次叠加层(不是路线更改)。 如何?

[英]Show overlay only once on page entrance (not route change). HowTo?

所以我尝试在我的 gatsby 站点上覆盖大约一秒钟,让它在后面加载正确的断点。 我怎样才能做到这一点?

所以我设置了一个 Interval 和一些 State 来加载 Overlay 并让它在一个间隔后消失。 但是每个页面重新加载覆盖层后的问题再次出现。 我没有像 redux 这样的状态管理,我需要 Overlay 只在每次刷新或从外部链接进入后出现,而不是点击内部链接。

我试过useEffect只在挂载上渲染,但这并不能解决问题,因为内部链接更改会触发重新挂载

我发现我可以使用浏览器 API onInitialClientRender。 但我不明白如何在 gatsby-browser.js 之外访问在那里生成的值。 一般来说,我在理解如何使用这些 API 时遇到问题。

自定义钩子.js

export function useInterval(callback, delay) {
  const savedCallback = useRef()

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback
  }, [callback])

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current()
    }
    if (delay !== null) {
      let id = setInterval(tick, delay)
      return () => clearInterval(id)
    }
  }, [delay])
}

布局.js

let [loadingIndicator, setLoadingIndicator] = useState(true)
const delay = 500

useInterval(() => {
  setLoadingIndicator(false)
}, delay)

因此,预期结果将是一种告诉初始客户端渲染设置状态的方法,该状态告诉覆盖要渲染,并且在此渲染之后状态应该更改以禁用覆盖的渲染。

解决方案:

使用 gatsby 更改静态 index.html 文件的能力。 [在 Gatsby 中自定义 Index.html][1]

向生成的 html.js 添加自定义 div

html.js:

   <div
      key={`loader`}
      id="___loader"
      style={{
        alignItems: "center",
        backgroundColor: "#F2F2F2",
        display: "flex",
        justifyContent: "center",
        position: "absolute",
        left: 0,
        top: 0,
        right: 0,
        bottom: 0,
        zIndex: 1,
      }}
   >
      <LoaderSVG width="50%" />
   </div>

在 gatsby-browser.js 中:

gatsby-browser.js:

export const onInitialClientRender = () => {
  document.getElementById("___gatsby").style.display = "block"
  setTimeout(function() {
    document.getElementById("___loader").style.display = "none"
  }, 200)
}

下一步是检查是否所有数据都加载完毕并添加一个动态值而不是超时。

我做了这样的事情。

我从 .cache 目录复制了默认的 html 并粘贴到 src 目录中。

我使用了以下命令:

cp .cache/default-html.js src/html.js

在 html.js 文件中,我注意到以下代码:

import React from "react"
import PropTypes from "prop-types"

export default function HTML(props) {
  return (
    <html {...props.htmlAttributes}>
      <head>
        <meta charSet="utf-8" />
        <meta httpEquiv="x-ua-compatible" content="ie=edge" />
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1, shrink-to-fit=no"
        />
        {props.headComponents}
      </head>
      <body {...props.bodyAttributes}>
        {props.preBodyComponents}
        <div
          key={`body`}
          id="___gatsby"
          dangerouslySetInnerHTML={{ __html: props.body }}
        />
        {props.postBodyComponents}
      </body>
    </html>
  )
}

HTML.propTypes = {
  htmlAttributes: PropTypes.object,
  headComponents: PropTypes.array,
  bodyAttributes: PropTypes.object,
  preBodyComponents: PropTypes.array,
  body: PropTypes.string,
  postBodyComponents: PropTypes.array,
}

我放了 SVG 加载器,它是一个图像和几行 CSS:

所以完整的代码是这样的:

import React from "react"
import PropTypes from "prop-types"
import LoaderSVG from './img/loader.svg'

export default function HTML(props) {
  return (
    <html {...props.htmlAttributes}>
      <head>
        <meta charSet="utf-8" />
        <meta httpEquiv="x-ua-compatible" content="ie=edge" />
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1, shrink-to-fit=no"
        />
        {props.headComponents}
      </head>
      <body {...props.bodyAttributes}>
        {props.preBodyComponents}
        <div
              key={`loader`}
              id="___loader"
              style={{
                alignItems: "center",
                backgroundColor: "#F2F2F2",
                display: "flex",
                justifyContent: "center",
                position: "absolute",
                left: 0,
                top: 0,
                right: 0,
                bottom: 0,
                zIndex: 1,
              }}
           >
              <img src={LoaderSVG} alt="" width="150"/>
        </div>
        <div
          key={`body`}
          id="___gatsby"
          dangerouslySetInnerHTML={{ __html: props.body }}
        />
        {props.postBodyComponents}
        <script
          dangerouslySetInnerHTML={{
            __html: `
                setTimeout(function() {
                    document.getElementById("___loader").style.display = "none"
                }, 200)
            `,
          }}
        />
      </body>
    </html>
  )
}

HTML.propTypes = {
  htmlAttributes: PropTypes.object,
  headComponents: PropTypes.array,
  bodyAttributes: PropTypes.object,
  preBodyComponents: PropTypes.array,
  body: PropTypes.string,
  postBodyComponents: PropTypes.array,
}

然后重启 Gatsby 就可以了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM