'ReactJS Reuse Modal for Add and Edit
I have a ReactJS application, I have a page that has a table there is a create button for creating a new record that opens a modal to enter the data. That works fine but I want to reuse that same modal to edit the data as well. The user can select a row and then click edit, but I don't seem to be able to get the data I need.
My Dialog is being included on the page as follows.
render() {
return (
<div>
<h2>Parameters</h2>
<div className="row">
<ParameterDialog callback={this.fetchFromApi} messageCallback={this.props.messageCallback} open={this.state.modalOpen} openCallback={this.openModal} closeCallback={this.closeModal} selectedParameter={this.state.selectedRow} selectedParameterCallback={this.getSelectedParameter} />
<div className="col-sm-10">
<button type="button" onClick={this.onDelete} className="btn btn-danger pull-right" style={{marginRight: '15px', width: '80px'}}><span className="glyphicon glyphicon-remove"></span> Delete</button>
<button type="button" onClick={this.onEdit} className="btn btn-warning pull-right" style={{marginRight: '15px', width: '80px'}}><span className="glyphicon glyphicon-edit"></span> Edit</button>
</div>
</div>
<BootstrapTable data={this.state.parameters} options={options} pagination selectRow={{mode: 'radio', onSelect: this.onRowSelect}}>
<TableHeaderColumn isKey dataField='id'>ID</TableHeaderColumn>
<TableHeaderColumn dataField='groupId' filterFormatted dataFormat={enumFormatter} formatExtraData={this.props.parentState.parameterGroups}
filter={{type: 'SelectFilter', options: this.props.parentState.parameterGroups}}>Category</TableHeaderColumn>
<TableHeaderColumn dataField='subGroupId' filterFormatted dataFormat={enumFormatter} formatExtraData={this.state.subGroups}
filter={{type: 'SelectFilter', options: this.state.subGroups}}>Sub Category</TableHeaderColumn>
<TableHeaderColumn dataField='name' filter={ { type: 'TextFilter', delay: 500 } }>Parameter</TableHeaderColumn>
<TableHeaderColumn dataField='type' filterFormatted dataFormat={enumFormatter} formatExtraData={this.props.parentState.parameterTypes}
filter={{type: 'SelectFilter', options: this.props.parentState.parameterTypes}}>Type</TableHeaderColumn>
<TableHeaderColumn dataField='reboot'>Reboot</TableHeaderColumn>
</BootstrapTable>
</div>
)
}
In the Dialog component I am calling trying to fetch the data in componentDidMount problem being it will always be null when the component mounts because user hasn't chosen anything yet.
componentDidMount() {
console.debug("ParameterDialog mounted...");
axios({
method: 'get',
url: urlBuilder.buildUrl('/api/groups'),
data: {},
}).then(resp => {
this.setState({groups: resp.data});
}).catch(error => {
this.props.messageCallback("Ohhhh snap!", "Unable to fetch data from server", Constants.MESSAGE_ERROR)
});
axios({
method: 'get',
url: urlBuilder.buildUrl(`/api/groups/2/subgroups`),
data: {}
}).then(resp => {
this.setState({subGroups: resp.data});
}).catch(error => {
this.props.messageCallback("Ohhhh snap!", "Unable to fetch data from server", Constants.MESSAGE_ERROR)
});
// init the state
this.setState({typeOptions: ['BOOLEAN', 'STRING', 'INTEGER', 'DECIMAL']});
this.setState({selectedGroup: 2, parameter: '', description: null, type: 'BOOLEAN', rebootRequired: false});
// if parameterId is present load record from database (Edit mode)
let parameterId = this.props.selectedParameterCallback();
if (parameterId) {
console.debug("Parameter is being edited, loading record");
this.editMode = true;
this.loadRecord();
}
}
The modal open property is being bound to parent, but what I really need to happen is when open changes it checked the selectedParameter value and then makes the decision to call the API or not.
return (
<div className="col-sm-2">
<Button bsStyle="primary" onClick={this.props.openCallback}>Add Parameter</Button>
<Modal show={this.props.open} onHide={this.closeCallback}>
<Modal.Header>
<Modal.Title>Add / Edit Parameter</Modal.Title>
</Modal.Header>
.........
However this seems to be in contrast to how ReactJS wants to work , the only thing I can think of is to move all the state into the parent component but that will make it huge and really doesn't seem like good module design.
Is there another way to accomplish this? If I could call a child function from parent that would accomplish what I need to do I think.
Solution 1:[1]
React is best for just managing the view, but not the actions behind the views.
I highly recommend using Redux to help with this. With Redux, you would have your AJAX calls in an action creator and your application state would be maintained in the reducer. That would simplify your React considerably and make it easier to maintain.
In regards to your question about where to maintain state, you would keep that in the Redux state using a reducer, and all of the state changes would propagate to your React components as props. You want to have a top-down hierarchical design so that the parent component (parent to the dialog) would pass the dialog content as a prop to the dialog. The dialog would send events to the action creator to do the loading and updating.
Solution 2:[2]
I do have the same problem but I think a have the logic in place, one way to do it is to create an initialstate of the form or object as empty strings, when an object is sent to the modal it will initialize the object with an id, if its new object render Addnew if an id is present then render Update item, you can implement other logics but this one seems to be simplest one
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Kelly Keller-Heikkila |
Solution 2 | Josue Garcia |