Search code examples
javascripthtmlreactjsreact-class-based-component

Changing properties of a state using a function within React.js class component


I have a basic audio playing app using react-h5-audio-player.

In its basic form, the AudioPlayer component takes a source, I have stored this media locally and am attempting to build a parent Player component around AudioPlayer as a parent that contains a function that switches the media source using a class component.

I have stored the title of the tracks as well as their data pathways in a single state containing three objects. I am looking to alter the source of the AudioPlayer, changing the data reference using a function.

Here is my code with some attempt to fill in the logic using psudo, these areas have Asterix around them:

import track1 from "../audio/01.mp3"
import track2 from "../audio/02.mp3"
import track3 from "../audio/03.mp3"

class Player extends React.Component {

    constructor(){
    super()

    this.state = [
        {title: "first track", data: track1},
        {title: "second track", data: track2},
        {title: "third track", data: track3},
    ]

    }

     changeData( **data value** ){
      **my new state = this.state[ data value ].data**
    }
  
    render(){
        return <div style={{color: this.props.color}}>
            <h1>Player</h1>
           <AudioPlayer
            src= {  **my new state**  }
            onPlay={e => console.log("onPlay")}
            // other props here
            />
            <div style={{color: "green"}}>
                <ul>
                    <li onClick={()=> this.changeData( **data value** )}>{this.state[0].title}</li>
                    <li onClick={()=> this.changeData( **data value** )}>{this.state[1].title}</li>
                    <li onClick={()=> this.changeData( **data value** )}>{this.state[2].title}</li>
                </ul>
            </div>
        </div>
    }
}

export default Player

Most of the guidance online has been about altering states and using this.setSate to change the entire state itself. I am struggling to use this as I am attempting to change / represent specific properties.

Any guidance or advice would be really appreciated! This my first time using gatsby / react.js so apologies if I am approaching this with the wrong logic.


Solution

  • For this, I will suggest using an additional state to handle the dynamic source for the audio player. Here is the sample for the same:

    import track1 from "../audio/01.mp3"
    import track2 from "../audio/02.mp3"
    import track3 from "../audio/03.mp3"
    
    class Player extends React.Component {
    
        constructor(){
        super()
    
        this.state = {
            tracks: [
              {title: "first track", data: track1},
              {title: "second track", data: track2},
              {title: "third track", data: track3},
            ],
            currentTrack: 0,
        }
    
        }
    
         changeData(trackIndex){
          this.setState({currentTrack: trackIndex})
        }
      
        render(){
            return <div style={{color: this.props.color}}>
                <h1>Player</h1>
               <AudioPlayer
                src= {this.state.tracks[this.state.currentTrack].data}
                onPlay={e => console.log("onPlay")}
                // other props here
                />
                <div style={{color: "green"}}>
                    <ul>
                        {this.state.tracks.map((trackElem, index) => (
                           <li onClick={()=> this.changeData(index)}>{trackElem.title}</li>
                        ))}
                    </ul>
                </div>
            </div>
        }
    }
    
    export default Player