Juan De Croche Juan De Croche - 2 months ago 4
React JSX Question

React modal reusing

I'm currently making a React application and I'm facing an issue.

I have a list with users, a button which displays a modal to add a user, and when you click a user from the list it shows you the same modal used to register users, but with the user information so you can modify it.

Everything is working good so far, when I open the modal I set the state binded to the modal to be the info from that user, the modal displays, I edit the user info, close it and the list refreshes instantanialy.

My issue is, in case that the user want to discard those changes, I can't get that the state changes don't persist.

I have a few workarounds in my head, for example can I save the state when the modal opens and if the user hit Discard I restore the saved state to the running state?

Im using bootstrap-react

var URL_ALL_USERS = "/api/users";

import Button from 'react-bootstrap/lib/Button';
import Modal from 'react-bootstrap/lib/Modal';
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
import FormGroup from 'react-bootstrap/lib/FormGroup';
import FormControl from 'react-bootstrap/lib/FormControl';
import Col from 'react-bootstrap/lib/Col';
import Form from 'react-bootstrap/lib/Form';
import ControlLabel from 'react-bootstrap/lib/ControlLabel';

var React = require('react');
var ReactDOM = require('react-dom');


var ISRBox = React.createClass({
getInitialState: function() {
return {searchData: [], profileData: {}, modalStatus: false};
},

updateList (newData) {
this.setState({searchData: newData});
},

openUserManager(userdata) {
this.setState({modalStatus: true, profileData: userdata});
},

closeUserManager() {
this.setState({modalStatus: false});
},

render: function() {
return (
<div className="isrBox">
<h1>ISR Manager </h1>
<button onClick={this.openUserManager}>Add User</button>

<UserHandle userdata={this.state.profileData} status={this.state.modalStatus} closeManager={this.closeUserManager}/>
<SearchForm clickHandler={this.updateList} url={URL_ALL_USERS}/>
<UserList data={this.state.searchData} onUserEdit={this.openUserManager}/>
</div>
);
}
});

var UserList = React.createClass({
render: function() {
var userNodes = this.props.data.map(function(user) {
return (
<tr className="rowStyle" onClick={() => this.props.onUserEdit(user)} key={user.id}>
<td>{user.email}</td>
<td>{user.name}</td>
<td>{user.info}</td>
<td>{user.lastlogin}</td>
</tr>
);
}, this);

return (
<div className="userList">
<table className="tableStyle">
<thead>
<tr>
<th>Email</th>
<th>User Name</th>
<th>Study, Site ID, Role</th>
<th>Last Login</th>
</tr>
</thead>

<tbody>
{userNodes}
</tbody>
</table>
</div>
);
}
});

var SearchForm = React.createClass({
getInitialState: function() {
return {
study: '',
site: '',
name: '',
email: '',
};
},

handleChange: function(name, event) {
var change = {};
change[name] = event.target.value;
this.setState(change);
},

search: function() {
$.ajax({
url: this.props.url +
"?study=" + this.state.study +
"&site=" + this.state.site +
"&name=" + this.state.name +
"&email=" + this.state.email,
dataType: 'json',
cache: false,
success: function(data) {
this.props.clickHandler(data);
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},

render: function() {
return (
<div className="searchForm" >
<div className="input">
<input
type="text"
placeholder="Study Code (full or partial) "
value={this.state.study}
onChange={this.handleChange.bind(this, 'study')}
/>
</div>

<div className="input">
<input
type="text"
placeholder="Site ID (full or partial) "
value={this.state.site}
onChange={this.handleChange.bind(this, 'site')}
/>
</div>

<div className="input">
<input
type="text"
placeholder="Name (full or partial) "
value={this.state.name}
onChange={this.handleChange.bind(this, 'name')}
/>
</div>

<div className="input">
<input
type="text"
placeholder="Email (full or partial) "
value={this.state.email}
onChange={this.handleChange.bind(this, 'email')}
/>
</div>

<div className="input">
<button onClick={this.search}>Do Search</button>
</div>
</div>
);
}
});

var UserHandle = React.createClass({

getInitialState() {
return {data: this.props.userdata};
},

refresh() {
this.setState({
data: this.props.userdata});
},

handleChange: function(name, event) {
var change = this.state.data;
change[name] = event.target.value;
this.setState({ showModal: true , data: change});
},

render() {
return (
<div>
<Modal show={this.props.status} onHide={this.props.closeManager} onEntering={this.refresh}>
<Modal.Header closeButton>
<Modal.Title>User Management</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form horizontal>

<FormGroup controlId="formEmail">
<Col componentClass={ControlLabel} sm={2}>
Email
</Col>
<Col sm={10}>
<FormControl type="email"
placeholder="Email"
value={this.state.data.email}
onChange={this.handleChange.bind(this, 'email')}/>
</Col>
</FormGroup>

<FormGroup controlId="formUser">
<Col componentClass={ControlLabel} sm={2}>
User
</Col>
<Col sm={10}>
<FormControl type="text"
placeholder="User name"
value={this.state.data.name}
onChange={this.handleChange.bind(this, 'name')}/>
</Col>
</FormGroup>

<FormGroup controlId="formComment">
<Col componentClass={ControlLabel} sm={2}>
Comment
</Col>
<Col sm={10}>
<FormControl type="text"
placeholder="User name"
value={this.state.data.comment}
onChange={this.handleChange.bind(this, 'comment')}/>
</Col>
</FormGroup>

</Form>
</Modal.Body>
<Modal.Footer>
<Button onClick={() => this.props.closeManager}>Close</Button>
</Modal.Footer>
</Modal>
</div>
);
}
});


ReactDOM.render(
<ISRBox />,
document.getElementById('content')
);


The problem is with UserHandle

Answer

I am not hundred percent sure but maybe you can do this

class AppContainer extends React.Component {
    constructor(props) {
        super();
        this.state = {
            previousName: '',
            name: 'Dan'
        };
    }

    editName(newName) {
        this.setState({
            previousName: this.state.name,
            name: newName
        });
    }

    restoreName() {
        this.setState({
            previousName: '',
            name: this.state.previousName
        });
    }
    render() {
        return(
            <App 
                {...this.state}
                editName={this.editName.bind(this)}
                restoreName={this.restoreName.bind(this)}
            />  
        );
    }
}
Comments