Wiem, że jest kilka podobnych pytań here i here, ale mam trudny czas zrozumieć, co jest prawidłowe myślenie dzisiaj na ten temat i ekstrapolować go do mojej sytuacji.react.js zadzwoń do funkcji rodzicielskiej od dziecka
Mam prostą aplikację, ScoreBox ma ScoreList, który ma wiele wyników. Chcę mieć Score onClick call ScoreList handleScoreRemove. Jestem pokazując pełny plik js, ale najważniejsze są linie linii 5 i linii 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')
);
Wszystkie 3 odpowiedzi były dobre, wybrałem ten, który był najłatwiejszy do naśladowania. Dzięki wszystkim, co pomogło. – Joelio