James
James

Reputation: 1475

With React, useState map trough state object, and create an array of audio elements.Then save audio duration to state as an array

I have the following array in my state:

tracks: [{
name: "Track A"
file: "https://urlto.mp3"
},
{
name: "Track B"
file: "https://urlto.mp3"
}
]

I am attempting to add key/pair values "duration":"X:XX" so that tracks becomes

tracks: [{
name: "Track A"
file: "https://urlto.mp3"
duration: "3:09"
},
{
name: "Track B"
file: "https://urlto.mp3"
duration: "1:04"
}
]

Where duration is created from the path to an mp3 file. I think I almost have it working but I cannot seem to add the new array to the existing array my code below gives me the following state:

tracks: [{
name: "Track A"
file: "https://urlto.mp3"
},
{
name: "Track B"
file: "https://urlto.mp3"
},
"3:09",
"1:04"
]

function makeAudio(tracks) {
    const ARR = new Array()
    for (let i = 0; i <= tracks.length; i++) {
      const au = document.createElement("audio")
      ARR.push(au)
    }
    console.log("makeAudio -> ARR", ARR)
    tracks.forEach((track, i) => {
      ARR[i].src = track.file
      ARR[i].addEventListener("loadedmetadata", function () {
        setState(state => ({
          ...state,
          tracks: state.tracks.concat(fmtMSS(ARR[i].duration)),
        }))
      })
    })
  }

Thanks in advance

Upvotes: 0

Views: 70

Answers (2)

James
James

Reputation: 1475

I ended up using Object.assign see below

function makeAudio(tracks) {
    let audioArr = new Array()
    tracks.forEach(({ file }) => {
      console.log(file)
      const audio = document.createElement("audio")
      audio.src = file
      audio.addEventListener("loadedmetadata", function () {
        audioArr.push([audio.duration])
        console.log("makeAudio -> audioArr", audioArr)
        setState(state =>
          Object.assign(
            {},
            state,
            tracks.map((track, index) =>
              Object.assign(track, { duration: audioArr[index] })
            )
          )
        )
      })
    })
  }

Upvotes: 0

Alessandro Scandone
Alessandro Scandone

Reputation: 157

Try this:

function makeAudio (tracks) {
  tracks.forEach(({ file }, i) => {
    const audio = document.createElement("audio")
    audio.src = file
    audio.addEventListener("loadedmetadata", () => {
      setState({
        ...state,
        tracks: tracks.map((track, i1) =>
          i !== i1 ? track : { ...track, duration: fmtMSS(audio.duration) }
        )
      })
    })
  })
}

Upvotes: 1

Related Questions