0

I am getting this error in my code. I am able to read the correct state from my Redux Chrome extension though. I don't know where is the error coming from. I think it comes from.

TopTracks.propTypes = {
  getHashParams: PropTypes.func.isRequired,
  getMyTopTracks: PropTypes.func.isRequired,      
  myTopTracks: PropTypes.arrayOf(PropTypes.object),
}

const mapStateToProps = state => ({
  myTopTracks: state.music.myTopTracks
})

Have I managed the mapStateToProps and PropTypes correctly? Because there is no sign of its object content: myTopTrackName and myTopTrackImage

Here is the full code:

class TopTracks extends Component{
  componentWillMount(){
    this.props.getMyTopTracks(getHashParams())
  }
  render(){
    let link = `${ window.location.href }`
    link = `/prueba/${link.substring(link.indexOf('#'))}`
    return(
      <div className="TopTracks">
          Now Playing: { this.props.myTopTracks[0].myTopTrackName }
          <img src={ this.props.myTopTracks[0].myTopTrackImage } alt="Top Track Album" style={{ width: 300 }} />
          <Button href={ link }>Continue</Button>
      </div>
    )
  }
}

TopTracks.propTypes = {
  getHashParams: PropTypes.func.isRequired,
  getMyTopTracks: PropTypes.func.isRequired,      
  myTopTracks: PropTypes.arrayOf(PropTypes.object),
}

const mapStateToProps = state => ({
  myTopTracks: state.music.myTopTracks
})

export default connect(mapStateToProps, { getHashParams, getMyTopTracks } )( TopTracks )

1 Answer 1

1

If the error is coming from the code shown, it means that this.props.myTopTracks is undefined, which in turns means that state.music.myTopTracks is undefined.

The real problem is in your app's initial state. Look in your redux reducers and make sure that your initial state sets myTopTracks to an empty array, []. This is a common, safe way to initialize the app state before you fetch the real list from the server.

You'll also still need to change your view code to account for an empty list, because myTopTracks[0] will be undefined if the list is empty. One way to solve that is by creating a safe default first object in the list, which would be replaced by incoming data from the fetch, such as:

{
  myTopTracks: [{
    myTopTrackName: 'Loading...',
    myTopTrackImage: ''
  }]
}

Another method is to check the length of the list, and if it's empty, render something else, like a spinner. It really depends on the design requirements for your app at that point. But those are two options.

Sign up to request clarification or add additional context in comments.

3 Comments

Oh, thank you!! But now I am getting problem if I ask for this.props.myTopTracks[1].myTopTrackName (when use a different number from 0
I am setting the state like this ` case SET_TOP_TRACKS: return { ...state, myTopTracks: [ { myTopTrackName: action.myTopTracks[0].myTopTrackName, myTopTrackImage: action.myTopTracks[0].myTopTrackImage }, { myTopTrackName: action.myTopTracks[1].myTopTrackName, myTopTrackImage: action.myTopTracks[1].myTopTrackImage },...`
No need to set each one individually. Just take the array from the action and put it directly in the state: case SET_TOP_TRACKS: return { ...state, myTopTracks: action.myTopTracks }.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.