反应子调用父方法无法访问状态

时间:2017-04-07 17:56:42

标签: javascript reactjs

我有3个嵌套App->GameList->GameItem

的组件

我在App(parent)组件上有一个方法可以通过onClick组件中的GameItem(child)事件进行调用

单击GameItem组件时,会触发App组件方法以访问App组件中的状态。

然而,当我尝试访问状态this.state.gamesVM时,我得到了

  

未捕获的TypeError:无法读取属性' gamesVM'为null

APP COMPONENT

export default class App extends React.Component {

  state = {
    userId: 3,
    gamesVM: [],
  }

  componentDidMount() {
    const pGames = getGames();
    const pPicks = getPicks();
    const pTeams = getTeams();

    Promise.all([pGames, pPicks, pTeams])
      .then(payload => {
        const gamesVM = this.getGamesVM(payload);
        this.setState({gamesVM});
      });
  }

  getGamesVM(payload) {
    // ... code to get and map gamesVM
  }

  teamPicked(team, away, home) { // gets called from child component
    console.log(this.state.gamesVM); // Uncaught TypeError: Cannot read property 'gamesVM' of null
    console.log(this.state.userId); // Uncaught TypeError: Cannot read property 'userId' of null
    // ...
    console.log(this.state.anything); // Uncaught TypeError: Cannot read property 'anything' of null
  }

  render() {
    return (
      <div className="App">
        <form onSubmit={this.handleSubmit}>
          <GameList
            gamesVM={this.state.gamesVM}
            teamPicked={this.teamPicked}
          />
          <input type="submit" value="Save" />
        </form>
      </div>
    );
  }
}

GAMELIST COMPONENT

export default class GameList extends React.Component {
  render() {
    return (
      <div className='matchups'>
        {this.props.gamesVM.map(game =>
          <GameItem
            teamPicked={this.props.teamPicked}
            key={game.id}
            {...game}
          />
        )}
      </div>
    )
  }
}

GAMEITEM COMPONENT

export default class GameItem extends React.Component {

  render() {

    let awayPickCheckbox = null;

    if (!this.props.isGameStarted) {

      awayPickCheckbox = <li>
            <input type="checkbox" id={this.props.id + this.props.awayTeam} />
            <label
              htmlFor={this.props.id + this.props.awayTeam}
              onClick={this.props.teamPicked.bind(this, 'away', this.props.id + this.props.awayTeam, this.props.id + this.props.homeTeam)}
            >
              {this.props.awayTeam}
            </label>
          </li>;

    } else {

      awayPickCheckbox = <li>
            <label>{this.props.awayTeam}</label>
          </li>
    }


    return (
      <div className="single-matchup">
        <ul className="away-team clearfix">
          {awayPickCheckbox}
        </ul>
      </div>
    )
  }
}

3 个答案:

答案 0 :(得分:2)

你需要使用this绑定方法。如果忘记绑定this.teamPicked并传递,则在实际调用该函数时,this将是未定义的。

内部构造函数functin,

this.teamPicked = this.teamPicked.bind(this)


 teamPicked(team, away, home) { // gets called from child component
    console.log(this.state.gamesVM); // Uncaught TypeError: Cannot read property 'gamesVM' of null
    console.log(this.state.userId); // Uncaught TypeError: Cannot read property 'userId' of null
    // ...
    console.log(this.state.anything); // Uncaught TypeError: Cannot read property 'anything' of null
  }

OR,

  render() {
    return (
      <div className="App">
        <form onSubmit={this.handleSubmit}>
          <GameList
            gamesVM={this.state.gamesVM}
            teamPicked={this.teamPicked.bind(this)}
          />
          <input type="submit" value="Save" />
        </form>
      </div>
    );
  }
}

答案 1 :(得分:1)

es6类中的函数不会自动绑定。

您可以将它们定义为属性和匿名函数,如下所示:

teamPicked = (team, away, home) => { // gets called from child component
    console.log(this.state.gamesVM); // Uncaught TypeError: Cannot read property 'gamesVM' of null
    console.log(this.state.userId); // Uncaught TypeError: Cannot read property 'userId' of null
    // ...
    console.log(this.state.anything); // Uncaught TypeError: Cannot read property 'anything' of null
  }

答案 2 :(得分:0)

我认为你必须删除绑定功能。

 <label
                  htmlFor={this.props.id + this.props.awayTeam}
                  onClick={this.props.teamPicked('away', this.props.id + this.props.awayTeam, this.props.id + this.props.homeTeam)}
            >