skip to Main Content

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?

2

Answers


  1. Chosen as BEST ANSWER

    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


    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>
    

    Your page is rendered without waiting for the async call to finish. By the time you refresh the async call has finished and therefore the script can be rendered.

    1. How can I debug and fix it?

    For debugging you could attach a function to the onLoad event of the script tag that fires a console.log.

    One solution would be to trigger a rerender in componentDidMount. This answer might be helpful.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search