Audio working from string, not working from JSX

I’m working on the Drum Machine project using React.

function Square({ value }) {
    const sounds = [
  {
    value: "Q",
    description: "quack",
    src: "https://sampleswap.org/samples-ghost/SOUND%20EFFECTS%20and%20NOISES/Sound%20FX%20Zoo%20and%20Nature/455[kb]duck-quacks.wav.mp3"
  }
]

    const src = sounds.find(sound => sound.value === value).src

    function handleClick() {
      const playPromise = audioRef.current.play() 
      
      if (playPromise !== undefined) {
        playPromise.then(() => {
          console.log("PLAY")
        }).catch(error => console.log(error))
      }
    }
    
  return (<>
    <button className="drum-pad" id={description} onClick={handleClick}>{value}
    </button>
    <audio 
        id={value}
        // src="https://sampleswap.org/samples-ghost/SOUND%20EFFECTS%20and%20NOISES/Sound%20FX%20Zoo%20and%20Nature/455[kb]duck-quacks.wav.mp3" // WORKS!
        // src={src}  //  Does not work, even though console.log says it's equivalent to string above
        ref={audioRef}
        streamType="mp3"
        crossOrigin = 'anonymous'
     />
   </>
  );
  }

For whatever reason, the audio works fine from the string. When using JSX, I get this error in Chrome:

DOMException: The element has no supported sources.

Same idea in FireFox:

NotSupportedError: The media resource indicated by the src attribute or assigned media provider object was not suitable.

I added crossOrigin = ‘anonymous’ because Stack Overflow says this is a CORS issue - but that doesn’t work and it doesn’t explain why the audio loads from the string.

Link to project: https://codepen.io/nicolejaneway/pen/xxrPaWR

Hi @NicoleJaneway, looking at your project I see you have all the Squares hardcoded but still a lot of them are missing a src value:

const sounds = [
  {
    value: "Q",
    description: "quack",
    src: "https://sampleswap.org/samples-ghost/SOUND%20EFFECTS%20and%20NOISES/Sound%20FX%20Zoo%20and%20Nature/455[kb]duck-quacks.wav.mp3",
    duration: 0,
  },
  {
    value: "W",
    description: "water",
    src: "",
    duration: 0,
  },
  {
    value: "E",
    description: "elephant",
    src: "",
    duration: 0,
  },
  {
    value: "A",
    description: "athlete",
    src: "",
    duration: 0,
  },
  {
    value: "S",
    description: "snake",
    src: "",
    duration: 0,
  },
  {
    value: "D",
    description: "dog",
    src: "",
    duration: 0,
  },
  {
    value: "X",
    description: "xylophone",
    src: "",
    duration: 0,
  },
  {
    value: "C",
    description: "cat",
    src: "",
    duration: 0,
  },
  {
    value: "Z",
    description: "zebra",
    src: "",
    duration: 0,
  }  
]

So for a lot of them src is undefined hence the error in console.

Also while we are at it, you are not really using React to its fullest potential:

 <div className="board-row">
            {renderSquare("Q")}
            {renderSquare("W")}
            {renderSquare("E")}
          </div>
          <div className="board-row">
            {renderSquare("A")}
            {renderSquare("S")}
            {renderSquare("D")}
          </div>
          <div className="board-row">
            {renderSquare("Z")}
            {renderSquare("X")}
            {renderSquare("C")}
          </div>

As you can see, you are manually creating all these pieces, while you could easily write a loop (done with map in React) to generate all this for you.
For a rough example you can map source and generate the pieces for you.

sources.map(source => <Square {...source} /> )

The above will create as many Square components as your source has, passing the values as prop.

Of course you pay the overhead of then using CSS properly to place them in a grid-like fashion. css grid can help you in that.

Please take the above with a grain of salt as I understand the extra complication of avoiding manual repetition. :slight_smile:
Hope this helps :sparkles:

Marmiz,
Thanks so much for looking over the project and providing these tips. While they don’t address the bug I’m focused on fixing, I do appreciate the suggestions :slight_smile:

Apologise if my message came up confusing, but your “bug” is happening because you don’t have src defined for all the audio files.

You are rendering them all, but only one (Q) has a valid src.

You can easily validate this by removing all other squares and just keep the Q, the error should disappear.
As well it should be fixed once you actually pass some valid data to your components.

Hope this helps clarifying things up. :slight_smile:

Thanks, Marmiz! Do you mind taking another look and seeing why you think it’s not working?

If you open your browser console, you will see some errors in there, they all states:

ReferenceError: handleKeyPress is not defined

Meaning that you have a method, in this case “handleKeyPress” which is not defined.

Once that’s added the error should go away.

My bad!! I thought I’d taken out all the references to the handleKeyPress function - sorry! Mind taking another look. Still can’t get the sounds to work.

const audioRef = useRef()

Are you sure you have this in the right place? Which component has the <audio> element?

Also, I’m not sure these sounds were meant to be accessed by a direct URL. They are loading very slowly for me and only work some of the time after clicking several times. I think these were meant to be downloaded and stored locally.

Are you able to play the sounds from the drum kit?

Yes, after fixing the first issue I mentioned the sounds do eventually play, but it takes a long time to load them and they don’t play consistently.

Interesting - okay, I’ll check it out

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.