使用地图时反应“无法读取未定义的属性" [英] React 'cannot read property of undefined' when using map

查看:44
本文介绍了使用地图时反应“无法读取未定义的属性"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从 teamtreehouse.com 制作一个非常基本的 React 应用程序,我经常遇到

<块引用>

类型错误:无法读取未定义的属性 'onPlayerScoreChange'"

即使我正确绑定了我的函数(我认为)

'onPlayerScoreChange'Grandparent 组件中的一个方法,当用户点击+"或-"按钮来改变玩家的分数时执行.

如果有人能解释什么是错的,那将非常有帮助,因为我想我在曾祖父母的构造函数中设置了 this.onPlayerScoreChange = this.onPlayerScoreChange.bind(this).

父组件:

class App 扩展 React.Component {构造函数(道具){超级(道具);this.onPlayerScoreChange = this.onPlayerScoreChange.bind(this)this.state = {initialPlayers: props.initialPlayers,};}onPlayerScoreChange(增量,索引){this.setState((prevState, props) => {返回 {initialPlayers: this.prevState.initialPlayers[index].score += delta}})}使成为() {返回(<div className = "记分牌"><标题标题 = {this.props.title}/><div className = "玩家">{this.state.initialPlayers.map(function(player, index) {返回(<播放器姓名 = {玩家.姓名}分数 = {player.score}键 = {player.id}索引 = {索引}onScoreChange = {this.onPlayerScoreChange}/>)})}

)}}

(组件有标题的默认道具)

子组件:

class Player 扩展 React.Component {使成为() {返回(<div className = "玩家"><div className = "玩家名称">{this.props.name}

<div className = "玩家分数"><Counter score = {this.props.score} onChange = {this.props.onScoreChange} index = {this.props.index}/>

)}}

孙组件:

class Counter 扩展 React.Component {构造函数(道具){超级(道具)this.handleDecrement = this.handleDecrement.bind(this)this.handleIncrement = this.handleIncrement.bind(this)}handleDecrement() {this.props.onChange(-1, this.props.index)}处理增量(){this.props.onChange(1, this.props.index)}使成为() {返回(<div className = "计数器"><button className = "counter-action decrement" onClick = {this.handleDecrement}>- </按钮><div className = "counter-score">{this.props.score} </div><button className = "counter-action increment" onClick = {this.handleIncrement}>+ </按钮>

)}}

谢谢!

解决方案

您还没有为您使用的地图函数绑定 onScoreChange = {this.onPlayerScoreChange},

您可以使用绑定或箭头函数进行绑定

附言需要绑定是因为 map 函数的上下文与 React Component 上下文不同,因此这个函数内的 this 不会引用 React 组件 this ,因此你无法访问 React Component 类的属性.

带箭头功能:

 {this.state.initialPlayers.map((player, index)=> {返回(<播放器姓名 = {玩家.姓名}分数 = {player.score}键 = {player.id}索引 = {索引}onScoreChange = {this.onPlayerScoreChange}/>)})}

有绑定

 {this.state.initialPlayers.map(function(player, index) {返回(<播放器姓名 = {玩家.姓名}分数 = {player.score}键 = {player.id}索引 = {索引}onScoreChange = {this.onPlayerScoreChange}/>)}.bind(this))}

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))}

这篇关于使用地图时反应“无法读取未定义的属性"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆