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
问题:
为什么会这样?
如何调试和修复它?
- 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>
您的页面无需等待异步调用完成即可呈现。当您刷新时,异步调用已完成,因此可以呈现脚本。
- How can I debug and fix it?
为了调试,您可以将一个函数附加到 script tag 的 onLoad
事件,该事件触发 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
目标:
加载站点后,导航栏中应该会出现搜索框和菜单项。
见下图:
问题:
目前在首次加载时 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
问题:
为什么会这样?
如何调试和修复它?
- 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>
您的页面无需等待异步调用完成即可呈现。当您刷新时,异步调用已完成,因此可以呈现脚本。
- How can I debug and fix it?
为了调试,您可以将一个函数附加到 script tag 的 onLoad
事件,该事件触发 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