Gatsby: Gatsby Context Consumer Causes 'WebpackError: TypeError: Cannot destructure property ' on Gatsby Build

Created on 4 Nov 2019  路  3Comments  路  Source: gatsbyjs/gatsby

Description

I'm using React context within Gatsby. When I'm running the app locally with gatsby develop, things works fine. When I try Gatsby build, I get errors on the functions I'm passing via React Context.

WebpackError: TypeError: Cannot destructure propertytogglePlayerof 'undefined' or 'null'.

Steps to reproduce

Player Context:

import React, { Component } from "react"


const PlayerContext = React.createContext()

export class PlayerProvider extends Component {
  constructor(props) {
    super(props)

    this.state = {
      isPlaying: false,
      currentlyPlayingSoundCloudTrack: '',
      drawerOpen:false
    }
  }


  togglePlayer = show => {
    if (show.id === this.state.currentlyPlayingSoundCloudTrack.id
    ) {
      this.setState(state => ({
        isPlaying: false,
        currentlyPlayingSoundCloudTrack: "",
      }))
    } else {
      this.setState(state => ({
        isPlaying: true,
        currentlyPlayingSoundCloudTrack: show,
      }))
    }
  }

  render() {
    const { children } = this.props

    console.log(this.state)

    return (
      <PlayerContext.Provider
        value={{
          togglePlayer: this.togglePlayer,
          currentlyPlayingSoundCloudTrack: this.state
            .currentlyPlayingSoundCloudTrack,
          isPlaying: this.state.isPlaying,

        }}
      >
        {children}
      </PlayerContext.Provider>
    )
  }
}

export const PlayerConsumer = PlayerContext.Consumer


A gatsby template or component that wants to use the context functions


 import React from "react";
import { withStyles } from "@material-ui/core/styles";
import { graphql } from "gatsby";
import { PlayerConsumer } from "../contexts/PlayerContext.js";
import { kebabCase } from "lodash";

const ItemPage = ({ data, classes }) => {
  //console.log(data);
  const item = data.item;

  return (
    <PlayerConsumer>
      {({ togglePlayer, currentlyPlayingSoundCloudTrack }) => (
        <div>
          {typeof currentlyPlayingSoundCloudTrack !== "undefined" &&
          item.id == currentlyPlayingSoundCloudTrack.id ? (
            <IconButton
              aria-label="Play/pause"
              className={classes.iconButton}
              onClick={() => togglePlayer(item)}
            >
              <Pause className={classes.playIcon} />
            </IconButton>
          ) : (
            <IconButton
              aria-label="Play/pause"
              className={classes.iconButton}
              onClick={() => togglePlayer(item)}
            >
              <PlayArrowIcon className={classes.playIcon} />
            </IconButton>
          )}
        </div>
      )}
    </PlayerConsumer>
  );
};

export default withStyles(styles)(ItemPage);

Expected result

Should call a function ok whether using gatsby build or develop

Actual result

When running 'gatsby build' , it breaks. But works fine on gatsby develop

Environment

System: OS: macOS 10.14 CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz Shell: 3.2.57 - /bin/bash Binaries: Node: 12.12.0 - /usr/local/bin/node Yarn: 1.19.1 - /usr/local/bin/yarn npm: 6.11.3 - /usr/local/bin/npm Languages: Python: 2.7.10 - /usr/bin/python Browsers: Chrome: 78.0.3904.70 Firefox: 70.0.1 Safari: 12.0 npmPackages: gatsby: ^2.17.7 => 2.17.7 gatsby-cli: ^2.8.8 => 2.8.8 gatsby-image: ^2.2.29 => 2.2.30 gatsby-plugin-manifest: ^2.2.25 => 2.2.26 gatsby-plugin-material-ui: ^2.1.6 => 2.1.6 gatsby-plugin-offline: ^2.0.25 => 2.2.10 gatsby-plugin-react-helmet: ^3.0.10 => 3.1.13 gatsby-plugin-remote-images: ^1.0.7 => 1.0.7 gatsby-plugin-sharp: ^2.2.32 => 2.2.33 gatsby-remark-copy-linked-files: ^2.0.11 => 2.1.28 gatsby-remark-images: ^3.0.1 => 3.1.28 gatsby-remark-relative-images: ^0.2.1 => 0.2.3 gatsby-source-filesystem: ^2.1.35 => 2.1.35 gatsby-transformer-remark: ^2.3.4 => 2.6.31 gatsby-transformer-sharp: ^2.1.9 => 2.3.1

Is there something I'm missing about using React context correctly with Gatsby?

question or discussion

Most helpful comment

I solved this with defaultState in the context provider


const defaultState = {
  togglePlayer: () => {},
  currentlyPlayingSoundCloudTrack: '',
  isPlaying: false,
  handleDrawerOpen:() => {},
  handleDrawerClose:() => {},
  drawerOpen:false
}

const PlayerContext = React.createContext(defaultState)

All 3 comments

Thank you for opening this!

This is most likely not related to Gatsby, as I can use context just fine in this codesandbox: https://codesandbox.io/s/gatsby-context-wknx8
I'd recommend asking for React advise in places like Reactiflux Discord or StackOverflow.

We're marking this issue as answered and closing it for now but please feel free to comment here if you would like to continue this discussion. We also recommend heading over to our communities if you have questions that are not bug reports or feature requests. We hope we managed to help and thank you for using Gatsby!

I solved this with defaultState in the context provider


const defaultState = {
  togglePlayer: () => {},
  currentlyPlayingSoundCloudTrack: '',
  isPlaying: false,
  handleDrawerOpen:() => {},
  handleDrawerClose:() => {},
  drawerOpen:false
}

const PlayerContext = React.createContext(defaultState)

I used the default state but had to include a check as well.

<div>
{defaultState && defaultState.isPlaying ? : "Start" : "Pause"}
<div>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

andykais picture andykais  路  3Comments

3CordGuy picture 3CordGuy  路  3Comments

ferMartz picture ferMartz  路  3Comments

dustinhorton picture dustinhorton  路  3Comments

timbrandin picture timbrandin  路  3Comments