Skip to content

Trying to convert class to hook style components #34

@wchorski

Description

@wchorski

I've taken a wack at trying to convert AudioAnalyser.js to a Hook style Component. I got stuck on one error

The Code

import React, { Component, useRef, useEffect, useState } from 'react';
import AudioVisualiser from './AudioVisualiser';

export const AudioAnalyser = ( { audio } ) => {
  // constructor(props) {
  //   super(props);
  //   this.state = { audioData: new Uint8Array(0) };
  //   this.tick = this.tick.bind(this);
  // }
  const isMounted = useRef()

  const [audioData, setAudioData] = useState(new Uint8Array(0))
  // const [audioContext, setaudioContext] = useState()
  // const [analyser, setAnalyser] = useState()
  // usest
  const audioContext = useRef(null)
  const analyser = useRef(new Uint8Array(0))
  const dataArray = useRef(null)
  const source = useRef(null)
  let rafId = useRef(null)

  useEffect(() => {
    if(!isMounted.current){
      handleMount() // mount logic
      isMounted.current = true 

    } else {
      if(!analyser.current) return 
      tick() // update logic
    }
  
    // return () => {
    //   cancelAnimationFrame(rafId.current);
    //   analyser.current.disconnect();
    //   source.current.disconnect();
    // }
  })
  

  async function handleMount() {
    try {
      // this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
      const newAudCtx = new (window.AudioContext || window.webkitAudioContext)()
      audioContext.current = newAudCtx

      const newAnlyzer = newAudCtx.createAnalyser()
      analyser.current = newAnlyzer

      const newDtArr = new Uint8Array(newAnlyzer.current.frequencyBinCount)
      dataArray.current = newDtArr

      const newSrc = audioContext.current.createMediaStreamSource(audio);
      source.current = newSrc

      newSrc.connect(newAnlyzer)
      const newRafId = requestAnimationFrame(tick())
      rafId.current = newRafId
      
    } catch (error) {
      console.warn('audio analyser mount fail');
    }
  }

  function tick() {
    if(!analyser.current) return 
    analyser.current.getByteTimeDomainData(dataArray.current);
    // setState({ audioData: this.dataArray });
    setAudioData(dataArray.current)
    rafId.current = requestAnimationFrame(tick());
  }



  return <AudioVisualiser audioData={audioData} />
}

export default AudioAnalyser;

The Error

[!error] TypeError: Failed to execute 'getByteTimeDomainData' on 'AnalyserNode': parameter 1 is not of type 'Uint8Array'.

function tick() {
  67 |   if(!analyser.current) return 
> 68 |   analyser.current.getByteTimeDomainData(dataArray.current);
     |                   ^
  69 |   // setState({ audioData: this.dataArray });
  70 |   setAudioData(dataArray.current)
  71 |   rafId.current = requestAnimationFrame(tick());

The Question

can't tell if this is an initialization issue or a order of operations issue. Any guidance on how to correct is greatly appreciated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions