javascript - 如何使用 SSG 处理 Next.js 中依赖 document.title 的代码?
问题描述
我在下面有 2 个动态 SSG 页面/blog/[slug]
,在这些页面中我正在渲染一个组件next/link
,我可以单击这些链接转到另一个 slug,问题是我想运行一些依赖于的代码document.title
,我尝试了可能的组合解决方案:
const ref = createRef<HTMLDivElement>()
useEffect(() => {
while (ref.current?.firstChild) {
ref.current.firstChild.remove()
}
const timeout = setTimeout(() => {
if (typeof window === "object") {
const scriptElement = document.createElement("script")
scriptElement.src = "https://utteranc.es/client.js"
scriptElement.async = true
scriptElement.defer = true
scriptElement.setAttribute("crossorigin", "annonymous")
scriptElement.setAttribute("repo", "my/repo")
scriptElement.setAttribute("issue-term", "title")
scriptElement.setAttribute("theme", "photon-dark")
ref.current?.appendChild(scriptElement)
}
}, 0)
return () => {
clearTimeout(timeout)
}
}, [])
...
return <div ref={ref} />
问题是在页面之间切换时 useEffect 不运行,此代码仅在我访问刷新页面时有效,如何在页面之间导航时使用此代码以使其使用最新的文档标题工作?
编辑:
const BlogPost = ({
recordMap,
post,
pagination,
}: InferGetStaticPropsType<typeof getStaticProps>) => {
if (!post) {
return null
}
const [script, setScript] = useState<HTMLScriptElement | null>(null)
const ref = createRef<HTMLDivElement>()
const router = useRouter()
useEffect(() => {
const handleRouteChange = () => {
const scriptElement = document.createElement("script")
scriptElement.src = "https://utteranc.es/client.js"
scriptElement.async = true
scriptElement.defer = true
scriptElement.setAttribute("crossorigin", "annonymous")
scriptElement.setAttribute("repo", "daniellwdb/website")
scriptElement.setAttribute("issue-term", "title")
scriptElement.setAttribute("theme", "photon-dark")
setScript(scriptElement)
}
router.events.on("routeChangeComplete", handleRouteChange)
return () => {
router.events.off("routeChangeComplete", handleRouteChange)
}
}, [])
useEffect(() => {
if (script) {
ref.current?.appendChild(script)
setScript(null)
} else {
ref.current?.firstChild?.remove()
}
}, [script])
return (
<>
<Box as="main">
<Container maxW="2xl" mb={16}>
<Button as={NextChakraLink} href="/" variant="link" my={8}>
Back to home page
</Button>
<NotionRenderer
className="notion-title-center"
recordMap={recordMap}
components={{
// Bit of a hack to add our own component where "NotionRenderer"
// would usually display a collection row.
// eslint-disable-next-line react/display-name
collectionRow: () => <BlogPostHero post={post} />,
code: Code,
equation: Equation,
}}
fullPage
darkMode
/>
<Pagination pagination={pagination ?? {}} />
<Box mt={4} ref={ref} />
<Footer />
</Container>
</Box>
</>
)
}
解决方案
您可以收听router.events:
useEffect(() => {
const handleRouteChange = (url, { shallow }) => {
//...
}
router.events.on('routeChangeComplete', handleRouteChange);
return () => {
router.events.off('routeChangeComplete', handleRouteChange)
}
}, [])
推荐阅读
- java - spring testng:无法加载ApplicationContext
- html - 禁用的按钮在 Angular 6 中不起作用
- java - 将 FlowControlSettings 中的 maxOutstandingElementCount 设置为 null 的后果?
- python - 如何获得当前的平均值。使用 R(最好)或 Python 在 Google AdWords API 中对关键字的 CPC 出价?
- ionic4 - Ionic 4:2列网格列表虚拟滚动问题
- compilation - 有没有办法在编译 rust 时有条件地编译 wasm_bindgen 属性?
- mysql - 如果一列或两列为空,则为 ISNULL,则为 0
- angular6 - Angular 6如何在库项目中而不是在应用程序项目中创建功能模块
- c++ - 获取从无符号到有符号的隐式转换溢出的警告
- node.js - CURL - 如何为 OATH2 Ping 联合身份验证传递用户名和密码?