2016-02-24 30 views
2

我一直在修改转换我的web应用程序中的一个页面,以使用反应而不是jQuery和Vanilla JS,但由于多么陌生,我陷入了困境我有反应。React - 如何在AJAX请求后更新状态

目前,在页面上我有一个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响应的格式与页面加载时提供的初始数据完全相同,我只是想弄清楚如何更新状态以便反应知道删除刚删除的记录。

同样,我想扩展它来复制我的编辑和创建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); 
    }, 
    // ... 
}); 

而且,只是为了尝试,包括所有相关的,删除按钮仍然有onClick={this.handleRemoveModelName}ModelNamereturn

回答

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); 
    }, 
    // ... 
}); 

父组件就可以决定应当如何回应此事,并做出相应的阿贾克斯呼叫。

这使得ModuleName成为“转储”组件。它与数据管理没有任何关系,只能呈现传递的数据。


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

+0

哇,谢谢你的答案菲利克斯 - 非常感谢。刚刚尝试一下。 – martincarlin87

+0

呃。我实际上对组件名称感到困惑。我刚才看到你已经在'ModelNames'中使用了状态。让我更新我的答案。 –

+0

是的,这是对的,对于混淆抱歉,通用名称使它变得更糟。我为表格组件使用复数,单行使用单数。 – martincarlin87

3

菲利克斯克林的回答上面,你就需要在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) 
    }); 
    }, 
    ... 
} 

替代的解决方案是在ModalNames这需要定义handleRemoveModelName在id中,调用ajax,并像你最初一样设置setState。

+0

感谢Kujira,我会试试看。 – martincarlin87