Reputation: 5822
I have this AddUser
component which which is a simple componnet that gets an email address, and a role from dropdownlist and then passes these two values to the parent component. Everything works fine other than one thing: if I first enter the email address and then choose the role it onChange()
doesn't get the value from dropdownlist and pass null to the parent component. But if I first choose role and then enter the email, onChange()
gets both values! How can I fix it?
This component has 3 props: roles
is a dictionary and I'm creating rolesList
from it to use it as data for DropdownList
(it's from react-widget
, https://jquense.github.io/react-widgets/docs/#/?_k=3fo3eq). The second prop is handleChange()
that set the states of the parent component. the 3th one ishandleAddNewUser()
that returns the values from form to the parent component.
export const AddUser = React.createClass({
getInitialState() {
return {
email: "",
selectedRole: "",
};
},
onChange() {
var email = this.email.value;
this.props.handleChange(email, this.state.selectedRole);
},
render() {
var rolesList = [];
for(var key in this.props.roles){
rolesList.push(key);
}
return(
<div >
<form onSubmit={this.props.handleAddNewUser}>
<label >New user email address:</label>
<input ref={(ref) => this.email = ref} name='email' type='email' onChange={this.onChange} required />
<label >Choose a role for new user:</label>
<DropdownList data={rolesList} value={this.state.selectedRole} name='rolesList' onChange={selectedRole => this.setState({ selectedRole })} />
<button type="submit" >Add user</button>
</form>
</div>
);
},
});
UPDATE: this is the code from parent component, handleChange()
sets the states for parent component. handleAddNewUser()
is supposed to use the states and make an ajax request to create new user. Right now it gets value for newUserEmail
but not the newUserRole
handleChange(email, selectedRole){
this.setState({newUserEmail: email})
this.setState({newUserRole: selectedRole})
},
handleAddNewUser(e) {
e.preventDefault();
// using its state, it supposed to make an ajax request and create a new user
}
Upvotes: 4
Views: 2718
Reputation: 3062
You can get the values from the submit handler if you want. Here is an example.
Edit: The component DropdownList
doesn't create a real select
form element, it just creates a bunch of div
elements. This is why the normal event.target
solution don't work. You do need a custom onChange handler for the component. Try the below. It will only set the state locally but that should be enough to get this data to any parent container. You haven't posted the code for this.props.handleChange
so there is no way to know what args it can take.
Edit2: Added submit handler to call 'this.props.handleChange' with correct data.
export const AddUser = React.createClass({
getInitialState() {
return {
email: "",
selectedRole: "",
};
},
onChange(e) {
this.setState({
[e.target.name]: e.target.value
})
},
onSubmit(e) {
e.preventDefault();
this.props.handleChange(this.state.email, this.state.selectedRole)
},
render() {
var rolesList = [];
for(var key in this.props.roles){
rolesList.push(key);
}
return(
<div >
<form onSubmit={this.onSubmit}>
<label >New user email address:</label>
<input ref={(ref) => this.email = ref} name='email' type='email' onChange={this.onChange} required />
<label >Choose a role for new user:</label>
<DropdownList ref={(ref) => this.role = ref} data={rolesList} value={this.state.selectedRole} name='rolesList' onChange={selectedRole => this.setState({ selectedRole })} />
<button type="submit" >Add user</button>
</form>
</div>
);
},
});
Note that this.setState({ [e.target.name]: e.target.value })
using square brackets like this is a way to set the object key without knowing the name ahead of time. In this case is will be whatever the name prop of the element is (email).
Upvotes: 3
Reputation: 596
You only call this.onChange()
when email input value changes.
So even on the first character you type the this.onChange
sends the email value and the this.role.value
which is ''
.
So add an if()
to check if role
has a valid value.
to check for role.value
inside onChange()
if(email.length > 0 && role.length > 0)
this.props.handleChange(email, role);
Upvotes: 0