Search code examples
gatsbygoogle-custom-search

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


Goal:

when site is loaded it should have the search box together with menu items in the navigation bar.

See the picture below: enter image description here

Problem:

Currently on first load the google custom search box doesn't appear. However, when you reload/refresh the page, it will appear as normal and functions as normal. But this is annoying as people might not know I have the search box until they refresh or reload the page. This is what it appears like on first load.

enter image description here

UPDATE: I asked around and it loads fine for some people. I tested it several times at my end, in incognito mode, it loads fine sometimes, and it doesn't sometimes (needs reload/refresh). So... not everybody can reproduce this problem all the time. I am curious on why it happens like that.

I have tried:

According to google's instruction, I have done things like below: In my gatsby project's nav component,

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>

I did use devtool and saw there seems to be nothing loaded into the div where search box is supposed to appear. I have no idea why is that.

UPDATE: Hi, I have since changed the "async" attribute to "defer" and tested it in private/incognito mode and here is the result:

LinuxMint:

Chromium : OK

Firefox: OK

Manjaro (Linux)

Chrome: OK

Firefox: flashes but doesn't load

Windows:

Firefox: still flashes and doesn't load

Edge: mostly OK but sometimes it doesn't work

Iphone:

Safari : needs refresh/reload twice before it appears

Chrome: OK

Android:

Chrome: OK

UPDATE: I've changed my search service to algolia now, so the live site isn't available for testing.

Here is a simpler version just made for testing purpose: LIVE DEMO as you can see, the search box briefly flashes then disappear.

The Code is as below:

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

Question:

  1. Why is this happening?

  2. How can I debug and fix it?


Solution

  • after reading Josh's post: The Perils of Rehydration I think the problem I encountered was similar. So I did something like this.

    I create a folder called hooks and write a ClientOnly.js there. As below:

    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
    

    Then I wrote another search.js in the component folder, as below:

    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
    

    Then I imported them whenever I need them as :

    <ClientOnly>
       <Search />
    </ClientOnly>
    

    Now everything seems to work. You can test it here: Live Demo