Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running into a build failure trying to create a 'new Audio()'...thingy? #19522

Closed
rchrdnsh opened this issue Nov 14, 2019 · 13 comments
Closed

Running into a build failure trying to create a 'new Audio()'...thingy? #19522

rchrdnsh opened this issue Nov 14, 2019 · 13 comments
Labels
type: question or discussion Issue discussing or asking a question about Gatsby

Comments

@rchrdnsh
Copy link

rchrdnsh commented Nov 14, 2019

So, I have an app I'm working on that has a persistent music player built into it using context and hooks, etc. I runs fine in development, but when I try to build it, I get the following error in the terminal:

failed Building static HTML for pages - 1.576s

 ERROR #95313 

Building static HTML failed for path "/offline-plugin-app-shell-fallback/"

See our docs page for more info on this error: https://gatsby.dev/debug-html


  195 | 
  196 |   const [state, setState] = useState({
> 197 |     audioPlayer: new Audio(),
      |                      ^
  198 |     tracks: trackList,
  199 |     currentTrackIndex: null,
  200 |     isPlaying: false,


  WebpackError: ReferenceError: Audio is not defined
  
  - MusicPlayerContext.js:197 MusicPlayerProvider
    src/player/MusicPlayerContext.js:197:22

I went to the debug-html page, but I don't really understand what's going on or how to fix it. The article talks about checking if window is defined, but I tried doing that here and got a bunch of linting errors and other issues by trying to wrap the new Audio() thingy in an if statement...I guess that's not ok?

So, yeah, don't really know what to do or how to fix the issue :-(

@gatsbot gatsbot bot added the type: question or discussion Issue discussing or asking a question about Gatsby label Nov 14, 2019
@rchrdnsh rchrdnsh changed the title Running into a build failure trying to create a new Audio()...thingy? Running into a build failure trying to create a 'new Audio()'...thingy? Nov 14, 2019
@wardpeet
Copy link
Contributor

Audio is not supported while we generate html files. Please checkout https://www.gatsbyjs.org/docs/using-client-side-only-packages/

We're marking this issue as answered and closing it for now but please feel free to reopen this and comment if you would like to continue this discussion. We hope we managed to help and thank you for using Gatsby! 💜

@rchrdnsh
Copy link
Author

hmmmm...I looked at that document but I don't really follow what the best approach for me would be. I have this inside an AudioContext document:

import React, { useState, useMemo, useContext, useEffect } from 'react'

const MusicPlayerContext = React.createContext([{}, () => {}])

const MusicPlayerProvider = props => {

  // a bunch of other code...

  const [state, setState] = useState({
    audioPlayer: new Audio(),
    currentTrackIndex: null,
    isPlaying: false,
  })

// a bunch of other code...

  return (
    <MusicPlayerContext.Provider
      value={{
        playTrack,
        playArticleTrack,
        togglePlay,
        currentTrackName,
        currentTrackArtist,
        currentTrackArtwork,
        currentTrackAudio,
        currentTime,
        setCurrentTime,
        formattedDuration,
        formattedTime,
        audioPlayer: state.audioPlayer,
        trackList,
        isPlaying: state.isPlaying,
        playPreviousTrack,
        playNextTrack,
      }}
    >
      {props.children}
    </MusicPlayerContext.Provider>
  )
}

// access global state from MusicPlayerContext
function useMusicPlayerState() {
  return useContext(MusicPlayerContext)
}

export { useMusicPlayerState, MusicPlayerProvider }

...so I guess is there a simpler way to make this work somehow? I'm using React Context to create the audio context for all music to flow through, so it seems odd to try and use any of the solutions provided in the linked document, no? I don't really have a clue as to how I would go about doing any of those other things as well, to be honest.

@henry-ns
Copy link

henry-ns commented Dec 21, 2019

@rchrdnsh I'm going through the same problem now. My solution is to use useRef for manipulation a tag <audio />

for example:

const audioRef = useRef({ current: null });

// on return
<audio ref={audioRef} />

File where I use this

@rchrdnsh
Copy link
Author

hmmmm...could I use a ref if it's outside of the return() statement? I think that's the part I'm a bit stuck on, as I'm using it inside a useState hook and I'm not using the <audio> element at all...🤔

@henry-ns
Copy link

I thought of adding a global audio tag and store the ref in context.

@rchrdnsh
Copy link
Author

rchrdnsh commented Jan 2, 2020

I don't know if that would work either, as I'm calling new Audio() inside of a useState declaration inside of a React Context file. It's not a simple <Audio> tag, unfortunately.

So stumped by this...

Do you have any thoughts on this @KyleAMathews ? Maybe an Async useState call? Is there such a thing as a useAsyncState hook? I can't seem to be able to wrap a useState call inside of an if statement to check if the window is defined.

@henry-ns
Copy link

henry-ns commented Jan 3, 2020

Try to install loadable-components or react-loadable and use it as a wrapper. I have not tested using new Audio() within a context, only outside. Out worked...

@rchrdnsh
Copy link
Author

rchrdnsh commented Jan 4, 2020

hmmm...looking at the documentation for both loadable-components and react-loadable and I just don't get how I'm supposed go about using them...I don't know, this is just a bit beyond me at the moment...so frustrated with gatsby :-/

@rchrdnsh
Copy link
Author

so, @universse came up with a simple and awesome solution for my issue, which was to declare the audioPlayer as an empty object, then inject the Audio() element in a useEffect hook, like so:

const [state, setState] = useState({
  audioPlayer: {},
  currentTrackIndex: null,
  isPlaying: false,
})

const [currentTime, setCurrentTime] = useState(state.audioPlayer.currentTime)

useEffect(() => {
  setState({
    audioPlayer: new Audio(),
    currentTrackIndex: null,
    isPlaying: false,
  })
}, [])

...and it builds now! XD

@fyfirman
Copy link

Thanks @rchrdnsh it's totally work.

@gastonfl
Copy link

rchrdnsh

You are a genius, thanks I adapted that to my code. The secret is new Audio inside useEffect
THANKS

@spearkkk
Copy link

spearkkk commented Feb 9, 2022

export default function Player({ url, className }) {
    const [playing, setPlaying] = useState(false);
    const [audio] = useState(typeof Audio !== "undefined" && new Audio(url));

    useEffect(() => {
        playing ? audio.play() : audio.pause()

    }, [playing])

// your codes

}

I refer this code

@wkezhi
Copy link

wkezhi commented Feb 15, 2022

THANK YOU @rchrdnsh you and @universse are literally lifesavers this issue was keeping me up at night

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: question or discussion Issue discussing or asking a question about Gatsby
Projects
None yet
Development

No branches or pull requests

7 participants