Google 自定义搜索框在我的 Gatsby 项目中首次加载时不出现,仅在重新加载或刷新时出现

Google Custom Search Box doesn't appear on first load in my Gatsby project, only appears when reloading or refreshing

目标:

加载站点后,导航栏中应该会出现搜索框和菜单项。

见下图:

问题:

目前在首次加载时 google 自定义搜索框不会出现。但是,当您 reload/refresh 页面时,它会正常显示并正常运行。但这很烦人,因为人们在刷新或重新加载页面之前可能不知道我有搜索框。这是第一次加载时的样子。

更新:我四处询问,它对某些人来说加载得很好。最后我测试了几次,在隐身模式下,它有时加载正常,有时却不能(需要 reload/refresh)。所以...不是每个人都能一直重现这个问题。我很好奇为什么会这样。

我试过了:

根据google's instruction,我做了如下的事情: 在我的 gatsby 项目的导航组件中,

import { Helmet } from "react-helmet"
...
 <Helmet>
    <script async src="https://cse.google.com/cse.js?cx=123:456"></script>
  </Helmet>
    <nav className="nav" >
      <div className="nav-container">
        <Link to="/">Home</Link>
        <Link to="/blog">All</Link>
        <Link to="/tags/food">Food</Link>
        <Link to="/tags/style">Style</Link>
        <Link to="/tags/living">Living</Link>
        <Link to="/tags/travel">Travel</Link>
        <Link to="/about">About</Link>  
        <div className="gcse-search"></div>
      </div> 
    </nav>

我确实使用了 devtool,但发现 div 应该显示搜索框的地方似乎没有加载任何内容。我不知道为什么会这样。

更新: 嗨,我已经将 "async" 属性更改为 "defer" 并在 private/incognito 模式下对其进行了测试,结果如下:

Linux薄荷:

铬:好的

Firefox:好的

Manjaro (Linux)

Chrome: 好的

Firefox:闪烁但不加载

Windows:

Firefox:仍然闪烁且未加载

边缘:大部分都可以,但有时不起作用

Iphone:

Safari : 需要 refresh/reload 两次才能出现

Chrome:好的

Android:

Chrome:好的

更新:我现在已将搜索服务更改为 algolia,因此无法使用实时站点进行测试。

这是一个简单的版本,只是为了测试目的而制作的:LIVE DEMO 如您所见,搜索框短暂闪烁然后消失。

代码如下:

import React from "react"
import { Helmet } from "react-helmet"

import Layout from "../components/layout"

import SEO from "../components/seo"

const IndexPage = () => (
  <>
  <Helmet>
    <script async src="https://cse.google.com/cse.js?cx=123:456"></script>
  </Helmet>
  <Layout>
    <SEO title="Home" />
    <h1>Here goes the Google search:</h1>
    <div className="gcse-search"></div>
  </Layout>
  </>
)

export default IndexPage

问题:

  1. 为什么会这样?

  2. 如何调试和修复它?

  1. Why is this happening?
<script 

  async // <- This is the reason why your search box does not appear on first load

  src="https://cse.google.com/cse.js?cx=123:456"

></script>

您的页面无需等待异步调用完成即可呈现。当您刷新时,异步调用已完成,因此可以呈现脚本。

  1. How can I debug and fix it?

为了调试,您可以将一个函数附加到 script tagonLoad 事件,该事件触发 console.log

一种解决方案是在 componentDidMount 中触发重新渲染。这 answer 可能会有帮助。

阅读 Josh 的 post 后:The Perils of Rehydration 我认为我遇到的问题是相似的。所以我做了这样的事情。

我创建了一个名为 hooks 的文件夹,并在其中写了一个 ClientOnly.js。如下:

import React, { useState, useEffect } from 'react'

function ClientOnly({ children, ...delegated }) {
    const [hasMounted, setHasMounted] = useState(false);

    useEffect(() => {
      setHasMounted(true);
    }, []);
    if (!hasMounted) {
      return null;
    }
    return (
      <div {...delegated}>
        {children}
      </div>
    );
  }

  export default ClientOnly

然后我在组件文件夹里又写了一个search.js,如下:

import React from "react"
import { Helmet } from "react-helmet"

const search = () => {
  return (
    <div>
      <Helmet>
        <script
          async
          src="https://cse.google.com/cse.js?cx=123:456"
        ></script>
      </Helmet>

      <div className="gcse-search"></div>
    </div>
  )
}


export default search

然后我在需要时将它们导入为:

<ClientOnly>
   <Search />
</ClientOnly>

现在似乎一切正常。你可以在这里测试它:Live Demo