react.js从孩子那里调用父函数 [英] react.js call parent function from child

查看:46
本文介绍了react.js从孩子那里调用父函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道在这里有一些类似的问题此处,但我遇到了麻烦时间了解今天对此有什么正确的想法,并将其推断出我的处境.

I know there are a few similar questions here and here but I am having a tough time understanding what is the correct thinking today on this and extrapolating it to my situation.

我有一个简单的应用程序,ScoreBox有一个ScoreList,其中包含许多分数.我想让Score onClick调用ScoreList handleScoreRemove.我正在显示完整的js文件,但是最重要的行是第5行和第77行.

I have a simple app, ScoreBox has a ScoreList which has many Scores. I want to have a Score onClick call ScoreList handleScoreRemove. I am showing the full js file, but the most important lines are line 5 and line 77.

var Score = React.createClass({
  removeRecord: function(e){
      // How do I do this?
      ScoreList.handleScoreRemove(e);
  },
  render: function() {
    var team1_style = (this.props.team1_score >= this.props.team2_score) ?
        {fontWeight: 'bold'} : {};
    var team2_style = (this.props.team2_score >= this.props.team1_score) ?
            {fontWeight: 'bold'} : {};
        return (
            <tr>
              <td style={team1_style}>{this.props.team1_name}:</td><td style={team1_style}>{this.props.team1_score}</td>
              <td style={team2_style}>{this.props.team2_name}:</td><td style={team2_style}>{this.props.team2_score}</td>
              <td><a hef="#" id={this.props.id} onClick={this.removeRecord}>remove</a></td>
            </tr>
    );
  }
});

var ScoreBox = React.createClass({
  loadScoresFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  handleScoreSubmit: function(score) {
    var scores = this.state.data;
    // Optimistically set an id on the new score. It will be replaced by an
    // id generated by the server. In a production application you would likely
    // not use Date.now() for this and would have a more robust system in place.
    score.id = Date.now();
    var newScores = scores.concat([score]);
    this.setState({data: newScores});
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      type: 'POST',
      data: score,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        this.setState({data: scores});
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    this.loadScoresFromServer();
    setInterval(this.loadScoresFromServer, this.props.pollInterval);
  },
  render: function() {
    return (
      <div className="scoreBox">
        <h1>Scores</h1>
        <ScoreList data={this.state.data} />
        <ScoreForm onScoreSubmit={this.handleScoreSubmit} />
      </div>
    );
  }
});

var ScoreList = React.createClass({
  handleScoreRemove: function(score) {
    var scores = this.state.data;
    var index_of_score = array.indexOf(score);
    var newScores = scores.splice(index_of_score, 1);
    this.setState({data: newScores});
    $.ajax({
      url: this.props.url + "/" + score[id],
      dataType: 'json',
      type: 'DELETE',
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        this.setState({data: scores});
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  render: function() {
    var scoreNodes = this.props.data.map(function(score) {
      return (
        <Score key={score.id} id={score.id} team1_name={score.team1_name} team1_score={score.team1_score} team2_name={score.team2_name} team2_score={score.team2_score} >
        </Score>
      );
    });
    return (
      <div className="scoreList">
        <table>
          <tbody>
            {scoreNodes}
          </tbody>
        </table>
      </div>
    );
  }
});

var ScoreForm = React.createClass({
  checkForCompleteForm: function(){
    if (this.state.team1_name.length > 0 && this.state.team2_name.length > 0 && this.state.team1_score.length > 0 && this.state.team2_score.length > 0)
    {
      // enable the button
      $("input[type=submit]").removeAttr('disabled');
    }

  },
  getInitialState: function() {
    return {id: '', team1_name: '', team1_score: '', team2_name: '', team2_score: ''};
  },
 handleChange : function (e) {
    // this is a generic handle change function that uses the html id to set the state instead of
    // having a bunch of if statements
    var stateObject = function() {
      var returnObj = {};
      returnObj[this.target.id] = this.target.value;
      return returnObj;
    }.bind(e)();
    // setState is async which makes this painful
    //  JCN - why when I pass checkForCompleteForm as 2nd param it doesnt work, but instead I need this
    // function bind stuff... need to understand exactly what this is doing
    this.setState( stateObject, function(){
        this.checkForCompleteForm();
    }.bind(this));
  },
  handleSubmit: function(e) {
    e.preventDefault();
    var team1_name = this.state.team1_name.trim();
    var team1_score = this.state.team1_score.trim();
    var team2_name = this.state.team2_name.trim();
    var team2_score = this.state.team2_score.trim();
    if (!team1_name || !team1_score ) {
      return;
    }
    this.props.onScoreSubmit({team1_name: team1_name, team1_score: team1_score,team2_name: team2_name, team2_score: team2_score });
    this.setState({team1_name: '', team1_score: '', team2_name: '', team2_score: ''});
  },
  render: function() {
    return (
      <form className="scoreForm" onSubmit={this.handleSubmit}>
        <input
          id='team1_name'
          type="text"
          placeholder="Team1 Name"
          value={this.state.team1_name}
          onChange={this.handleChange}
        />
        <input
          id='team1_score'
          type="number"
          placeholder="Team1 Score"
          value={this.state.team1_score}
          onChange={this.handleChange}
        />
        <input
          id='team2_name'
          type="text"
          placeholder="Team2 Name"
          value={this.state.team2_name}
          onChange={this.handleChange}
        />
        <input
          id='team2_score'
          type="number"
          placeholder="Team2 Score"
          value={this.state.team2_score}
          onChange={this.handleChange}
        />
        <input type="submit" value="Post" disabled />
      </form>
    );
  }
});

ReactDOM.render(
  <ScoreBox url="/api/scores" pollInterval={2000} />,
  document.getElementById('content')
);

推荐答案

您需要通过 props

var scoreNodes = this.props.data.map(function(score) {
  return <Score
    key={score.id}
    id={score.id}
    team1_name={score.team1_name}
    team1_score={score.team1_score}
    team2_name={score.team2_name}
    team2_score={score.team2_score}
    handleScoreRemove={this.handleScoreRemove.bind(this)}>
  </Score>
}, this);

并在 Score 组件中这样称呼它

removeRecord: function(e) {
   this.props.handleScoreRemove( /* add arguments what do you need */ );
},

这篇关于react.js从孩子那里调用父函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆