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?
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