Goal:
when site is loaded it should have the search box together with menu items in the navigation bar.
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.
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:
-
Why is this happening?
-
How can I debug and fix it?
2
Answers
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:
Then I wrote another search.js in the component folder, as below:
Then I imported them whenever I need them as :
Now everything seems to work. You can test it here: Live Demo
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.
For debugging you could attach a function to the
onLoad
event of the script tag that fires aconsole.log
.One solution would be to trigger a rerender in
componentDidMount
. This answer might be helpful.