0

I am learning react and am stuck on an issue. I have 3 components, TransactionsDetails, TransactionForm and TransactionsTable.

TransactionsDetails TransactionForm TransactionsTable 

The records are saved in TransactionsDetails's state.records and are displayed in TransactionsTable. I am trying to add, edit, update, delete records. I have successfully added the add and delete functionality but am stuck on the edit and update. So, in the table rows, i have edit and delete button for each row. When clicked on edit, it should load the record data in the form and when clicked in save/submit, it should update the record.

 var TransactionForm = React.createClass({ getInitialState: function(){ return { date: '', amount: '' }; }, handleChange: function(e){ switch(e.target.name){ case 'date': this.setState({date: e.target.value}); break; case 'amount': this.setState({amount: e.target.value}); break; } }, handleSubmit: function(e){ e.preventDefault(); this.props.handleNewRecord(this.state); this.setState(this.getInitialState()); }, render: function(){ return ( <form onSubmit={this.handleSubmit} className="form-horizontal"> <div className="form-group"> <label for="date" className="col-sm-2 control-label">Date: </label> <div className="col-sm-10"> <input type='text' name='date' className="form-control" value={this.state.date} onChange={this.handleChange}/> </div> </div> <div className="form-group"> <label for="amount" className="col-sm-2 control-label">Amount: </label> <div className="col-sm-10"> <input type='integer' name='amount' className="form-control" value={this.state.amount} onChange={this.handleChange}/> </div> </div> <div className="form-group"> <div className="col-sm-offset-2 col-sm-10"> <button className="btn btn-primary" type='submit'>Submit</button> </div> </div> </form> ); } }); var TransactionRow = React.createClass({ handleDelete: function(e){ e.preventDefault(); this.props.handleDeleteRecord(this.props.record); }, handleEdit: function(e){ e.preventDefault(); this.props.handleEditRecord(this.props.record); }, render: function(){ return ( <tr> <td>{this.props.record.date}</td> <td>{this.props.record.amount}</td> <td> <button className="btn btn-primary" onClick={this.handleEdit}>Edit</button> <button className="btn btn-danger" onClick={this.handleDelete}>Delete</button> </td> </tr> ); } }); var TransactionsTable = React.createClass({ render: function(){ var rows = []; this.props.records.map(function(record, index){ rows.push(<TransactionRow key={index} record={record} handleDeleteRecord={this.props.handleDeleteRecord} handleEditRecord={this.props.handleEditRecord}/>); }.bind(this)); return ( <table className="table table-striped table-hover table-bordered"> <thead> <tr> <th> Date </th> <th> Amount </th> <th> Actions </th> </tr> </thead> <tbody> { rows } </tbody> </table> ); } }); var TransactionsDetails = React.createClass({ getInitialState: function(){ return { records: [ { date: '1-6-2016', amount: 1000}, { date: '2-6-2015', amount: -400} ] }; }, addRecord: function(record){ var records = this.state.records; records.push(record); this.setState({ records: records }); }, deleteRecord: function(record){ var records = this.state.records; var index = records.indexOf(record); records.splice(index, 1); this.setState({ records: records }); }, editRecord: function(record){ if(record){ return record; } else { return {}; } }, render: function(){ return ( <div className="container"> <div className='row'> <div className="col-md-4"> <div className="well"> <TransactionForm handleNewRecord={this.addRecord} record={this.editRecord()} /> </div> </div> </div> <div className='row'> <div className="col-md-offset-2 col-md-8"> <div className="well"> <TransactionsTable records={this.state.records} handleDeleteRecord={this.deleteRecord} handleEditRecord={this.editRecord}/> </div> </div> </div> </div> ); } }); 
5
  • So where are you stuck? What do you expect to happen? What is currently happening? Commented Jun 3, 2016 at 19:26
  • Not sure if someone mentioned it to you but to try to make this kind of thing easier Facebook (And a lot of other people that use React) use some kind of Flux implementation to try to solve this problem gracefully. Commented Jun 3, 2016 at 23:51
  • @BenHare thanks for the tip. I am a newbie to React. Anyways, when i get this working, i will try to do it the 'flux' way. BTW, could you please point to any links that solve the above problem the right way? thanks. Commented Jun 4, 2016 at 6:48
  • @gravityplanx currently, when i click the edit button, the record(to be edited) is passed to the editRecord function defined in TransactionsDetails. From there, it needs to be loaded in the TransactionForm and should be able to be updated. Commented Jun 4, 2016 at 6:50
  • Here's Facebook's explanation of what Flux is and why they use it, should be a good start: facebook.github.io/flux/docs/overview.html Commented Jun 4, 2016 at 12:30

1 Answer 1

1

I make the edit, delete and add record working according to your code with less modification in order to respect your code style and original

capture

var TransactionForm = React.createClass({ getInitialState: function(){ return { date: '', amount: '' }; }, handleChange: function(e){ switch(e.target.name){ case 'date': this.setState({date: e.target.value}); break; case 'amount': this.setState({amount: e.target.value}); break; } }, componentWillReceiveProps: function(nextProps) { if(nextProps.recordToEdit.index != this.props.recordToEdit.index) { this.setState(nextProps.recordToEdit.record) } }, handleSubmit: function(e){ e.preventDefault(); if(this.props.recordToEdit.index > -1) { this.props.handleUpdateRecord(this.props.recordToEdit.index, this.state); } else { this.props.handleNewRecord(this.state); } this.setState(this.getInitialState()); }, render: function(){ return ( <form onSubmit={this.handleSubmit} className="form-horizontal"> <div>{this.props.recordToEdit.index > -1 ? 'Edit mode' : 'Create mode'}</div> <div className="form-group"> <label for="date" className="col-sm-2 control-label">Date: </label> <div className="col-sm-10"> <input type='text' name='date' className="form-control" value={this.state.date} onChange={this.handleChange}/> </div> </div> <div className="form-group"> <label for="amount" className="col-sm-2 control-label">Amount: </label> <div className="col-sm-10"> <input type='integer' name='amount' className="form-control" value={this.state.amount} onChange={this.handleChange}/> </div> </div> <div className="form-group"> <div className="col-sm-offset-2 col-sm-10"> <button className="btn btn-primary" type='submit'>Submit</button> </div> </div> </form> ); } }); TransactionForm.defaultProps = { recordToEdit: { index: -1, record: {}} }; var TransactionRow = React.createClass({ render: function(){ return ( <tr> <td>{this.props.record.date}</td> <td>{this.props.record.amount}</td> <td> <button className="btn btn-primary" onClick={this.props.handleEditRecord}>Edit</button> <button className="btn btn-danger" onClick={this.props.handleDeleteRecord}>Delete</button> </td> </tr> ); } }); var TransactionsTable = React.createClass({ render: function(){ var rows = this.props.records.map(function(record, index){ return <TransactionRow key={index} record={record} handleDeleteRecord={() => this.props.handleDeleteRecord(index)} handleEditRecord={() => this.props.handleEditRecord(index, record)}/>; }.bind(this)); return ( <table className="table table-striped table-hover table-bordered"> <thead> <tr> <th> Date </th> <th> Amount </th> <th> Actions </th> </tr> </thead> <tbody> { rows } </tbody> </table> ); } }); var TransactionsDetails = React.createClass({ getInitialState: function(){ return { records: [ { date: '1-6-2016', amount: 1000}, { date: '2-6-2015', amount: -400} ], recordToEdit: { index: -1, record: {} } }; }, addRecord: function(record){ var records = this.state.records; records.push(record); this.setState({ records: records }); }, deleteRecord: function(index){ console.log(index) var records = [].concat(this.state.records); records.splice(index, 1); this.setState({ records: records }); }, updateRecord: function(index, record){ var records = [].concat(this.state.records) records[index] = record; this.setState({ records: records }); }, editRecord: function (index, record) { this.setState({ recordToEdit: { index: index, record: record } }) }, render: function(){ return ( <div className="container"> <div className='row'> <div className="col-md-4"> <div className="well"> <TransactionForm handleNewRecord={this.addRecord} handleUpdateRecord={this.updateRecord} recordToEdit={this.state.recordToEdit} /> </div> </div> </div> <div className='row'> <div className="col-md-offset-2 col-md-8"> <div className="well"> <TransactionsTable records={this.state.records} handleDeleteRecord={this.deleteRecord} handleEditRecord={this.editRecord}/> </div> </div> </div> </div> ); } }); 

To make this working I introduce "index" to be able to identify the record to delete or to update, and also a recordToEdit on the Details component state

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.