Jan
Jan

Reputation: 16094

Consuming useContext in a Gatsby page

Summary

.

What I try: I have a layout page, which contains a sidebar, footer,.. and as well a content page (e.g.: /pages/home)

I am searching a way to consume a React context within this regular /pages/home.js within

Relevant information

I have build a Context:

import React, { useState, createContext } from "react"

const ShareContext = createContext()
const ShareContextProvider = props => {
  const [collapsedShare, setCollapsedShare] = useState(false)
  const toggleShare = () => setCollapsedShare(!collapsedShare)

  return (
    <ShareContext.Provider value={{ collapsedShare, toggleShare: toggleShare }}>
      {props.children}
    </ShareContext.Provider>
  )
}

export { ShareContextProvider, ShareContext }

And wrapped it around my layout.js :


import { ShareContextProvider } from "../context/ShareContext"
const Layout = props => {
  return <ShareContextProvider>{props.children}</ShareContextProvider>
}

I can "consume" it within my sidebar, which is called in one of my layouts (I have a witch for more then one) which I do like this:

sidebar.js

import React, { useContext } from "react"
import { ShareContext } from "../../context/ShareContext"
const Sidebar = ({ siteTitle }) => {
  const { collapsedShare, toggleShare } = useContext(ShareContext)
  return (
    <>
       <div
          onClick={toggleShare}
          className={classNames("show-share showshare", {
            clshbt: collapsedShare,
          })}
        >
           Some content here
      </div>
</>
)
}

Now my question: How can I consume the context within a page (e.g. /pages/home.js?

import React, { useContext } from "react"
import { ShareContext } from "../context/ShareContext"

  const { collapsedShare } = useContext(ShareContext) <<<<------ When I add this line, everything breaks

When I try to use the same approach like in my sidebar.js it wont work and throws an error:

react.development.js:1465 Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https :// fb .me/react-invalid-hook-call for tips about how to debug and fix this problem.

I have to mention, that I am quite new on Gatsby and React

I've created a template which points out the problem: https://github.com/exocode/gatsby-context-problem

Many thanks in advance

Upvotes: 3

Views: 3148

Answers (2)

Quinma
Quinma

Reputation: 1476

I ran into the same problem then realized as you said the hook must be in the body of a function component. Since your context is inside the layout then you can only use context in a child component of layout.

A page component is a parent of layout, so do the following:

// src/pages/mypage.js
export default function MyPage() {
  return (<Layout><PageContentComponent /></Layout>);
}

const PageContentComponent = () => {
  const shareContext = useContext(shareContext);
  return <>...</>
}

Upvotes: 3

David F.
David F.

Reputation: 65

like the error message says: Hooks can only be called inside of the body of a function component.

That means you can only call it within a react functional component like so

const MyComponent = () => {
  const { collapseShare } = useContext(ShareContext)
}

See if that works!

Upvotes: 0

Related Questions