MrVoland
MrVoland

Reputation: 283

Gatsby - Uncaught TypeError - Context/build problem

I was developing my application in Gatsby and got stuck. Everything is working fine with "gatsby develop", but when I run "gatsby build" I get an error:

"WebpackError: TypeError: Cannot destructure property 'cursorStyles' of 'Object(...)(...)' as it is undefined."

And yeah, cursorStyles are defined in the context, so everything should work perfectly or I am missing something. Tried to clean cache, but still the error occurs, which is very weird cuz didn't have any problems to work on this project locally.

EDIT - yes, I wrapped the gatsby application with the Global Provider as you can see below. I just don't understand why the build doesn't work, when I clearly have the access to the context... ;/

gatsby-browser.js

import React from "react"
import { GlobalProvider } from "./src/context/globalContext"

export const wrapRootElement = ({ element }) => {
  return <GlobalProvider>{element}</GlobalProvider>
}

Context - values are defined in global provider const

import React, { createContext, useReducer, useContext } from "react"

//Define Context
const GlobalStateContext = createContext()
const GlobalDispatchContext = createContext()


//Reducer
const globalReducer = (state, action) => {
    switch (action.type) {
      case "TOGGLE_THEME": {
        return {
          ...state,
          currentTheme: action.theme,
        }
      }
      case "CURSOR_TYPE": {
        return {
          ...state,
          cursorType: action.cursorType,
        }
      }
      default: {
        throw new Error(`Unhandled action type: ${action.type}`)
      }
    }
  }



  export const GlobalProvider = ({ children }) => {
    const [state, dispatch] = useReducer(globalReducer, {
      currentTheme: "dark",
      cursorType: false,
      cursorStyles: ["pointer", "hovered", "locked", "white"],
    })

    return (
        <GlobalDispatchContext.Provider value={dispatch}>
          <GlobalStateContext.Provider value={state}>
            {children}
          </GlobalStateContext.Provider>
        </GlobalDispatchContext.Provider>
      )
}

//custom hooks for when we want to use our global state
export const useGlobalStateContext = () => useContext(GlobalStateContext)

export const useGlobalDispatchContext = () => useContext(GlobalDispatchContext)

Layout.js - problem occurs when destructuring and using my custom hook

import React, {useState} from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"

import { createGlobalStyle, ThemeProvider } from "styled-components"
import { normalize } from "styled-normalize"

import Header from './header'
import Cursor from './customCursor'
import Navigation from './navigation'

import { useGlobalStateContext, useGlobalDispatchContext } from '../context/globalContext'


const Layout = ({ children }) => {
  const { cursorStyles, currentTheme } = useGlobalStateContext()
  const dispatch = useGlobalDispatchContext()
  const data = useStaticQuery(graphql`
    query SiteTitleQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
  `)

  const darkTheme = {
    background: '#000',
    text:'#fff',
    red: '#ea291e'
  }

  const lightTheme = {
    background: '#fff',
    text:'#000',
    red: '#ea291e'
  }

  const onCursor = cursorType => {
    cursorType = (cursorStyles.includes(cursorType) && cursorType || false)
    dispatch({ type: "CURSOR_TYPE", cursorType: cursorType})
  }

  const [toggleMenu, setToggleMenu] = useState(false)

  return(
    <ThemeProvider theme={currentTheme === "dark" ? darkTheme : lightTheme}>
    <GlobalStyle/>
    <Cursor toggleMenu={toggleMenu} />
    <Header onCursor={onCursor} toggleMenu={toggleMenu} setToggleMenu={setToggleMenu} />
    <Navigation onCursor={onCursor} toggleMenu={toggleMenu} setToggleMenu={setToggleMenu} />
    <main>{children}</main>
    {console.log(currentTheme)}
    </ThemeProvider>
  ) 
  
  
}

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout

Upvotes: 4

Views: 1102

Answers (2)

Vasily Muravyev
Vasily Muravyev

Reputation: 1

Very strange. This problem happens only in production. Duplicating the code from gatsby-browser inside gatsby-ssr - really solves it!

import React from 'react';
import CartProvider from './src/components/CartProvider';
export const wrapRootElement = ({ element }) => (
  <CartProvider>{element}</CartProvider>
);

Upvotes: 0

MrVoland
MrVoland

Reputation: 283

Finally I solved it! I don't know why, but I guess it's just Gatsby who works in a mysterious way. I duplicated my code from gatsby-browser, and put exactly the same thing into the gatsby-ssr file and... surprisingly the weird errors about "object undefined" disappeared.

Unfortunately, due to the fact that gatsby build in that case works similar to the next.js' server-side rendering, I had to fix my code in different places - e.g "window" properties had to be rendered conditionally - but duplicating gatsby-browser's code to the gatsby-ssr fixed the building problem! So as I thought, it wasn't a problem with my code, but rather a problem with gatsby's config.

Upvotes: 4

Related Questions