我知道有一些类似的问题here和here但我很难理解今天的正确思考是什么,并根据我的情况进行推断。
我有一个简单的应用程序,ScoreBox有一个ScoreList,它有很多分数。我希望得到一个得分onClick调用ScoreList handleScoreRemove。我正在显示完整的js文件,但最重要的行是第5行和第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')
);
答案 0 :(得分:10)
您需要将handleScoreRemove
传递给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 */ );
},
答案 1 :(得分:3)
从孩子那里调用父功能
你不喜欢(就像其他帖子所说的那样)。您将 handleScoreRemove
传递给孩子作为道具。在孩子内部,你通过调用prop来调用该函数。在下文中,handleScoreRemove
作为onScoreRemove
道具传递给孩子。
<Score ...stuff... onScoreRemove={this.handleScoreRemove}></Score>
您已经使用ScoreBox
(父级)和ScoreForm
(子级)做同样的事情。您已在孩子中传递handleScoreSubmit
onScoreSubmit
道具的引用。
<ScoreForm onScoreSubmit={this.handleScoreSubmit} />
答案 2 :(得分:2)
您应将handleScoreRemove
作为道具传递给Score
:
ScoreList
:
var scoreNodes = this.props.data.map(function(score) {
return (
<Score key={score.id} (...) handleScoreRemove={this.handleScoreRemove}>
</Score>
);
});
Score
:
removeRecord: function(e){
this.props.handleScoreRemove(this);
}