FES
FES

Reputation: 43

How can I map a concatenated value for this state, without it being passed as a string?

I'm new to Javascript.

I'm building this drumpad and I want to be able to switch between different soundpacks.

The sounds are imported from a separate file and the state is written like this:

import * as Sample from '../audiofiles/soundfiles'

    const drumpadData = [
        {
            // other stuff
            soundfile: Sample.sound1a
        },

If I want to load a different soundpack, I have to change the state so the last letter (a,b,c) gets changed, so instead of Sample.sound1a, it would have to be Sample.sound1b. this is the function i wrote (on App.js):

changeSamples(id) {
    let choice = document.getElementById("select-samplepack").value
    this.setState(prevState => {
        const updatedData = prevState.data.map(item => {
            let newSoundfile = "Sample.sound" + item.id + choice
            item.soundfile = newSoundfile
            return item
        })
        return {
            data: updatedData
        }
    })
}  

It works, as in the value gets changed, but instead of react interpreting that and finding the correct import, the value of soundfile just stays as a string like "Sample.soundb1", so I get a load of media resource errors.

https://aquiab.github.io/drumpad/ heres the website, you can check the console to see the error, you have to load a different soundpack to reproduce the error.

https://github.com/aquiab/drumpad and here are the files:

I've thought of some ways of cheesing it, but I want the code to stay as clean as I can make it be.

Upvotes: 3

Views: 90

Answers (3)

Cat_Enthusiast
Cat_Enthusiast

Reputation: 15688

Well that's because it is in fact a string. When you do:

"Sample.Sound" + item.id + choice you are doing type coersion. In JavaScript, that means you are converting the value of all data-types so that they share a common one. In this case your output resolves into a string. This will not be effective in finding the right sound in your dictionary.

Instead, what you need is bracket notation: Object[property] Within the brackets we can define logic to identify the designated key belonging to the Object.

For example: Sample["sound" + item.id + choice] would evaluate to Sample["sound1b"] which is the same as Sample.sound1b

changeSamples(id) {
    let choice = document.getElementById("select-samplepack").value
    this.setState(prevState => {
        const updatedData = prevState.data.map(item => {
            item.soundfile = Sample["sound" + item.id + choice]
            return item
        })
        return {
            data: updatedData
        }
    })
}  

Upvotes: 1

Julien Lemaître
Julien Lemaître

Reputation: 125

Your problem comes from this line :

let newSoundfile = "Sample.sound" + item.id + choice

Here you are concatening your values item.id and choice with a string, so the result is a string and Sample is not interpreted as your imported object.

What you need is to wright something like

const sampleItem = "sound" + item.id + choice
let newSoundfile = Sample[sampleItem]

When you access an object property with the notation myObject[something], what's inside the bracket get interpreted. So in my example sample (which is a string because I concatenated a string "sound" with the variables) will be replaced with its string value (ex: "sound1a"), and newSoundFile will have as value the result of Sample["sound1a"].

I hope it make sens.

Upvotes: 1

Jitesh Manglani
Jitesh Manglani

Reputation: 485

I can think of two approaches here.

  1. import Sample in App.jsx. and update sound file.

 import * as Sample from '../audiofiles/soundfiles'
       
       changeSamples(id) {
        let choice = document.getElementById("select-samplepack").value
        this.setState(prevState => {
            const updatedData = prevState.data.map(item => {
                let newSoundfile = Sample[`sound${item.id}${choice}`]
                item.soundfile = newSoundfile
                return item
            })
            return {
                data: updatedData
            }
        })
    }

  1. You should save mapping of files in other object and update mapping and use mapping in drumpadData soundfile key.

Upvotes: 1

Related Questions