React - 如何在AJAX请求后更新状态

时间:2016-02-24 16:19:44

标签: javascript ajax reactjs

我一直在修改我的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

2 个答案:

答案 0 :(得分:3)

除了Felix Kling的答案之外,您需要以某种方式在ModalNamesModalName之间进行通信以更新状态,因为状态由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;零件。它与数据管理没有任何关系,只会呈现传递的数据。

另一个问题是你正在阅读ModelNamesthis.props.model_names)中的道具,而不是州。国家和道具是不同的。您需要从状态(this.state.model_names)读取,以便在状态更改时更新组件。