React 'cannot read property of undefined' when using map

react tutorial
react get
react native
react router
react-bootstrap
react hooks
create react app
react.js example

I'm making a very basic React app from teamtreehouse.com, and I'm constantly encountering

"TypeError: Cannot read property 'onPlayerScoreChange' of undefined"

even though I'm binding my functions correctly (I think)

'onPlayerScoreChange' Is a method in the Grandparent component which executes when a user hits a '+' or '-' button to change a player's score.

It would be really helpful if someone could explain what is wrong, because I think I am setting this.onPlayerScoreChange = this.onPlayerScoreChange.bind(this) in the great grandparent's constructor.

Parent component:

class App extends React.Component {
constructor(props) {
    super(props);
    this.onPlayerScoreChange = this.onPlayerScoreChange.bind(this)
    this.state = {
        initialPlayers: props.initialPlayers,
    };
}

onPlayerScoreChange(delta, index) {
    this.setState((prevState, props) => {
        return {initialPlayers: this.prevState.initialPlayers[index].score += delta}
    })
}

render() {
    return(
        <div className = "scoreboard">
            <Header title = {this.props.title}/>
            <div className = "players">
                {this.state.initialPlayers.map(function(player, index) {
                    return(
                        <Player 
                        name = {player.name} 
                        score = {player.score} 
                        key = {player.id} 
                        index = {index}
                        onScoreChange = {this.onPlayerScoreChange}
                        />
                    )
                })}
            </div>
        </div>
    )
}}

(Component has default props for title)

Child component:

class Player extends React.Component {
render() {
    return(
        <div className = "player">
            <div className = "player-name">
                {this.props.name}
            </div>
            <div className = "player-score">
                <Counter score = {this.props.score} onChange = {this.props.onScoreChange} index = {this.props.index}/>
            </div>
        </div>
)
}}

Grandchild component:

class Counter extends React.Component {
constructor(props) {
    super(props)
    this.handleDecrement = this.handleDecrement.bind(this)
    this.handleIncrement = this.handleIncrement.bind(this)
}

handleDecrement() {
    this.props.onChange(-1, this.props.index)
}

handleIncrement() {
    this.props.onChange(1, this.props.index)
}

render() {
    return(
        <div className = "counter">
            <button className = "counter-action decrement" onClick = {this.handleDecrement}> - </button>
            <div className = "counter-score"> {this.props.score} </div>
            <button className = "counter-action increment" onClick = {this.handleIncrement}> + </button>
        </div>
)}}

Thank you!

You have not done binding for the map function where you are using onScoreChange = {this.onPlayerScoreChange},

you can either use bind or arrow functions for binding

P.S. Binding is needed because the context of the map function is different from the React Component context and hence this inside this function won't be Referring to the React Components this and thus you can't access that properties of the React Component class.

With Arrow function:

 {this.state.initialPlayers.map((player, index)=> {
                return(
                    <Player 
                    name = {player.name} 
                    score = {player.score} 
                    key = {player.id} 
                    index = {index}
                    onScoreChange = {this.onPlayerScoreChange}
                    />
                )
            })}

With bind

   {this.state.initialPlayers.map(function(player, index) {
                return(
                    <Player 
                    name = {player.name} 
                    score = {player.score} 
                    key = {player.id} 
                    index = {index}
                    onScoreChange = {this.onPlayerScoreChange}
                    />
                )
            }.bind(this))}

React (web framework), React is an open-source JavaScript library for building user interfaces. It is maintained by Facebook and a community of individual developers and companies. Simple to use yet advanced data visualization library for your React web apps.

Can also be done by passing second argument as this to map function as onClick event uses local this of map function which is undefined here and this currently refers to the global object.

{this.state.initialPlayers.map(function(player, index) {
                    return(
                        <Player 
                        name = {player.name} 
                        score = {player.score} 
                        key = {player.id} 
                        index = {index}
                        onScoreChange = {this.onPlayerScoreChange}
                        />
                    )
                }),this}

facebook/react: A declarative, efficient, and flexible , React is a JavaScript library for building user interfaces. Declarative: React makes it painless to create interactive UIs. Design simple views for each state in your  React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Declarative views make your code more predictable and easier to debug.

sometimes it is quite easy and it all depends on how you declare your loop

example you will get this error if you try to do something like this var.map(function(example, index) {}

but if you call the new function within the map with this

this.sate.articles.map(list => 
{<a onClick={() => this.myNewfunction()}>{list.title}</a>)}

the second loop will get you out of the undefined error

and dont forget to bind your new function

React.js cheatsheet, React.Component · render() · componentDidMount() · props/state · dangerouslySetInnerHTML · React is a JavaScript library for building user interfaces. React definition is - to exert a reciprocal or counteracting force or influence —often used with on or upon. How to use react in a sentence.

What is React, If an attribute is wrapped in curly braces, the value is a JavaScript expression. Note that JSX does not use quotes around the HTML text string. React DOM Render. to act reciprocally upon each other, as two things. to act in a reverse direction or manner, especially so as to return to a prior condition. to act in opposition, as against some force. to respond to a stimulus in a particular manner: reacting to a shock by jumping; to react to the word “coward” with anger.

React Tutorial, React Tutorial. ❮ Home Next ❯. React is a JavaScript library for building user interfaces. React is used to build single page applications. v.i. 1. to act in response to an agent, influence, stimulus, etc.: to react to a drug; reacted to the noise by jumping. 2. to act reciprocally upon each other, as two things. 3. to act in a reverse direction or manner, esp. so as to return to a prior condition.

React Redux · Official React bindings for Redux, React Redux is maintained by the Redux team, and kept up-to-date with the latest APIs from Redux and React. Predictable. Designed to work with React's  React – Changing Advertising for Good stratweb 2019-11-22T15:20:36-05:00 The impulse to multi-task strikes when content goes to break. What will audiences DO and VIEW when your REVENUE STREAM appears?

Comments
  • forgot to bind in map, use this: {this.state.initialPlayers.map((player, index) => {
  • Thank you! makes a lot of sense now
  • Possible duplicate of "this" is undefined inside map function Reactjs