Reputation: 977
I'm using ReactJS and I need to change the status of the values but the value property is in the state in this way:
this.state = {
form:{
name:{
value:''
}
}
}
I tried it in different ways on the form like:
<TextInput
name='form.name.value'
value={this.state.form.name.value}
onChange={value => this.onChange('name', value)}
/>
onChange = (e) => {
this.setState({ [e.target.name]: e.target.value})
}
But never changes the value on state.
How can I do this? thanks!!!!!!
Upvotes: 2
Views: 213
Reputation: 4059
Your onChange
function should be changed to
onChange = (e) => {
this.setState({ form: {...this.state.form, [e.target.name]: e.target.value}})
}
Edit: I was able to run the below code successfully
class App extends React.Component {
state = {
form: {
test: ""
}
}
onChange = (e) => {
this.setState({
form: {
...this.state.form,
[e.nativeEvent.target.name]: e.target.value,
}
})
}
render() {
return <div>
<TextInput
name='test'
value={this.state.form.test}
onChange={this.onChange}
/>
<br/><br/>
The State : {JSON.stringify(this.state)}
</div>;
}
}
const TextInput = (props) => {
return <input type="text" {...props}/>;
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
Edit: As per your new structure I have made the changes
class App extends React.Component {
state = {
form: {
test: {
value: "",
type: "text"
}
}
}
onChange = (e) => {
this.setState({
form: {
...this.state.form,
[e.nativeEvent.target.name]: {
...this.state.form[e.nativeEvent.target.name],
value: e.nativeEvent.target.value
},
}
})
}
render() {
return <div>
<CustomInput
name='test'
value={this.state.form.test.value}
onChange={this.onChange}
/>
<br/><br/>
The State : {JSON.stringify(this.state)}
</div>;
}
}
const CustomInput = (props) => {
return <input {...props}/>;
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>
Upvotes: 1
Reputation: 1556
You need to use destructuring wiht es6:
I have created a working copy here: CodePen InputForm
var sp = {...this.state.form};
sp.name.value = event.target.value;
this.setState({sp})
Upvotes: 0
Reputation: 2087
The way you have used the input field name is incorrect.In the setState
it is considered as string rather than a object.key
.
onChange= (e) => {
let inputName = e.target.name;
let inputValue = e.target.value;
let updatedFormState = Object.assign({}, this.state);
updatedFormState.form[inputName].value = inputValue;
this.setState(updatedFormState);
}
Upvotes: 1
Reputation: 3062
I dont know your scenario but I think you are doing wrong practice. Solution to you problem:
<TextInput
name="form.name.value"
value={this.state.form.name.value}
onChange={(a, b) => this.handleTextChange(a, b)}
/>
Now handleTextChange
like
handleTextChange(name, value) {
const arr = name.split(".");
const obj = {
[arr[2]]: value
};
const nameObj = {
[arr[1]]: { ...obj }
};
console.log("fomr", nameObj);
this.setState({ form: nameObj });
}
Considering you customComponent
const TextInput = props => {
return (
<input
name={props.name}
onChange={e => props.onChange(e.target.name, e.target.value)}
/>
);
};
CodeSandbox working example
Upvotes: 0
Reputation: 33974
In order to setState for a nested object you can follow the below approach as I think setState doesn't handle nested updates.
let form = {...this.state.form}
let name = [e.target.name];
form.name = e.target.value;
this.setState({form});
The idea is to create a dummy object perform operations on it and then replace the component's state with the updated object
Upvotes: 0