Reputation: 188
I have a script that works fine in the gatsby dev server but when trying to run gatsby build I get an error stating
"document" is not available during server side rendering.
The error fires on this code snippet
const useActiveElement = () => {
const [active, setActive] = useState(document.activeElement)
I assume that this error is also present any place I use document
in this file, maybe outside of the useEffect
places I use document
. However, I have not been able to properly convert the code to using react hooks in a way that would allow Gatsby to build. Any suggestions on what I should do?
The full file (minus imports)
const useActiveElement = () => {
const [active, setActive] = useState(document.activeElement)
const handleKeyup = (e) => {
if (e.keyCode === 9) setActive(document.activeElement)
}
useEffect(() => {
document.addEventListener("keyup", handleKeyup)
return () => {
document.removeEventListener("keyup", handleKeyup)
}
}, [])
return active
}
const Layout = ({
children,
crumbLabel,
subStatus,
parentPageLabel,
parentPageLink,
}) => {
const focusedElement = useActiveElement()
const data = useStaticQuery(graphql`
query SiteTitleQuery {
sanitySiteSettings {
title
}
}
`)
useEffect(() => {
const prevTabbedElements = document.getElementsByClassName("tabbed")
for (let i = 0; i < prevTabbedElements.length; i++) {
prevTabbedElements[i].classList.remove("tabbed")
}
focusedElement.value && focusedElement.value.classList.add("tabbed")
focusedElement.classList.add("tabbed")
}, [focusedElement])
return (
<>
<Header siteTitle={data.sanitySiteSettings.title}/>
<nav>
{subStatus ? (
<Parentcrumbs
crumbLabel={crumbLabel}
parentPageLabel={parentPageLabel}
parentPageLink={parentPageLink}
/>
) : (
<Breadcrumbs crumbLabel={crumbLabel}/>
)}
</nav>
<main>{children}</main>
<Footer/>
</>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
Upvotes: 3
Views: 2354
Reputation: 29320
At the initial render point, your document
is not defined yet so:
const useActiveElement = () => {
const [active, setActive] = useState('')
const handleKeyup = (e) => {
if (e.keyCode === 9) setActive(document.activeElement)
}
useEffect(() => {
setActive(document.activeElement);
document.addEventListener("keyup", handleKeyup)
return () => {
document.removeEventListener("keyup", handleKeyup)
}
}, [])
return active
}
Init the useState
as empty and fill in in your componentDidMount
(useEffect
with empty deps
).
Upvotes: 4