2016-02-24 42 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