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

IT技术 javascript reactjs gatsby grommet
2021-04-30 02:19:03

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

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

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

我发现我可以在InitialClientRender 上使用浏览器API。但我不明白如何在 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)

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

2个回答

解决方案:

使用 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 就可以了。