我一直在修改我的Web应用程序中的一个页面以使用反应而不是jQuery和Vanilla JS,但是由于我对这种反应有多么不熟悉,我会陷入如何处理它的问题。
目前,在页面上我有一个html表,其中包含与数据库表相关的行,另一列包含编辑和删除行的链接。
这是通过打开引导模式来完成的,该模式包含为编辑操作填充适当行的表单,以及用于确认删除的删除模式,页面上还有一个链接可以通过AJAX添加新行所以我要做的就是复制这个反应,但我似乎无法理解如何去做。
目前我有这个(我在这个例子中使用通用组件名称(ModelName
),以避免与实际调用的内容混淆。):
var ModelNames = React.createClass({
getInitialState: function() {
return {model_names: this.props.model_names};
},
render: function() {
var rows = [];
this.props.model_names.forEach(function(model_name) {
rows.push(<ModelName model_name={model_name} key={model_name.id} />);
});
return (
<div className="row">
<div className="col-md-12">
<table className="table table-striped table-bordered table-hover">
<thead>
<tr role="row" className="heading">
<th>Property 1</th>
<th>Property 2</th>
<th className="text-center">Options</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
</div>
</div>
);
}
});
var ModelName = React.createClass({
handleRemoveModelName: function() {
$.ajax({
url: '/model_name/ajax_delete',
data: { model_name_id: this.props.model_name.id },
type: 'POST',
cache: false,
success: function(data) {
this.setState({ model_names: data }); // this is the part I am having trouble with
}.bind(this),
error: function() {
console.log('error');
}.bind(this)
});
},
render: function() {
return (
<tr id={"model_name_" + this.props.model_name.id}>
<td>{this.props.model_name.property_1}</td>
<td>{this.props.model_name.property_2}</td>
<td className="text-center">
<a href="javascript:;" className="btn btn-xs" onClick={this.handleEditModelName}><i className="fa fa-pencil"></i></a> <a href="javascript:;" className="btn btn-xs" onClick={this.handleRemoveModelName}><i className="fa fa-remove"></i></a>
</td>
</tr>
);
}
});
ReactDOM.render(
// this comes from Rails
<ModelName model_names={<%= @model_names.to_json %>} />,
document.getElementById('react')
);
通过ajax删除工作正常,服务器端响应数据库表中的所有行(删除发生后),因此json响应的格式与页面加载时提供的初始数据完全相同,我只想弄清楚如何更新状态,以便react知道删除我刚刚删除的记录。
同样,我想扩展它以复制我的编辑和创建CRUD功能,但在阅读大量博客文章后,我很难找到所需的信息。
更新
var ModelNames = React.createClass({
handleRemoveModelName: function(id) {
$.ajax({
url: '/model_name/ajax_delete',
data: { model_name_id: id },
type: 'POST',
cache: false,
success: function(data) {
this.setState({ model_names: data });
}.bind(this),
error: function() {
console.log('error');
}.bind(this)
});
},
render: function() {
var rows = [];
this.props.model_names.map(function(model_name) {
return (
<ModelName
model_name={model_name}
key={model_name.id}
onRemove={this.handleRemoveModelName}
/>
);
}, this);
// ...
}
});
var ModelName = React.createClass({
handleRemoveModelName: function() {
this.props.onRemove(this.props.model_name.id);
},
// ...
});
此外,只是尝试包含所有相关内容,“{1}} onClick={this.handleRemoveModelName}
的删除按钮仍然有ModelName
。
答案 0 :(得分:3)
除了Felix Kling的答案之外,您需要以某种方式在ModalNames
和ModalName
之间进行通信以更新状态,因为状态由ModalNames
管理并且事件被调用在ModalName
。
一种解决方案是将更新状态的函数传递给ModalName
:
ModalNames:
var ModelNames = React.createClass({
...
updateState: function(modal_names) {
this.setState({modal_names})
},
render: function() {
var rows = [];
this.state.model_names.forEach(function(model_name) {
rows.push(<ModelName model_name={model_name} key={model_name.id} updateState={this.updateState} />);
});
...
}
}
ModalName:
var ModelName = React.createClass({
handleRemoveModelName: function() {
$.ajax({
url: '/model_name/ajax_delete',
data: { model_name_id: this.props.model_name.id },
type: 'POST',
cache: false,
success: function(data) {
this.props.updateState(data);
}.bind(this),
error: function() {
console.log('error');
}.bind(this)
});
},
...
}
替代解决方案是在handleRemoveModelName
中定义ModalNames
,其中包含id,调用ajax,并像您最初一样执行setState。
答案 1 :(得分:1)
您必须决定数据的真实来源。在您当前的设置中,它似乎位于ModelNames
。
不要让ModelName
执行删除操作,而是让ModelNames
执行此操作,因为它拥有数据。
只需将回调传递给请求删除时调用的ModelName
。在这个例子中,我们向子组件onRemove
添加一个新属性,当单击删除按钮时调用该组件:
var ModelNames = React.createClass({
handleRemoveModelName: function(id) {
// make Ajax call here
},
render: function() {
var rows = this.state.model_names.map(function(model_name) {
return (
<ModelName
model_name={model_name}
key={model_name.id}
onRemove={this.handleRemoveModelName}
/>
);
}, this);
// ...
}
});
var ModelName = React.createClass({
handleRemoveModelName: function() {
this.props.onRemove(this.props.model_name.id);
},
// ...
});
然后,父组件可以决定如何响应它并进行适当的Ajax调用。
这使ModuleName
成为&#34;转储&#34;零件。它与数据管理没有任何关系,只会呈现传递的数据。
另一个问题是你正在阅读ModelNames
(this.props.model_names
)中的道具,而不是州。国家和道具是不同的。您需要从状态(this.state.model_names
)读取,以便在状态更改时更新组件。