Reputation: 15
I have a Form Component where it contains a state that should be updated (on input change) and it looks like this:
import { useState } from 'react';
export const Test = () => {
const [state, setState] = useState({
name: 'khaled',
age: 18
})
const handleInputChange = (e) => {
let stateCopy = state
for(let key in stateCopy) {
if(key === 'name') {
stateCopy[key] = e.target.value;
}
}
setState(stateCopy);
}
return(
<div>
<span>Name</span>
<input onChange={ handleInputChange } />
<span>{state.name}</span>
</div>
)
}
and it imported in the app component
import { Test } from '../../components/Test';
function App() {
return (
<Test />
);
}
export default App;
and whenever i try to change the name inout it not update the ui
Upvotes: 1
Views: 950
Reputation: 474
simply do it like this, it will work
const handleInputChange = (e) => {
setState({...state, name: e.target.value})
}
Upvotes: 0
Reputation: 555
This does not work because your "stateCopy" object isn't actually a copy, its the actual state object. you are setting the state to the same object which causes react to think the state didn't change at all.
instead you should copy the state like this
const handleInputChange = (e) => {
let stateCopy = {...state}
state.name = e.target.value
setState(stateCopy);
}
You should also note that unless there is a good reason for your choice of state in my opinion you should use a seperate useState for each element in the state which results in the much simpler
import { useState } from 'react';
export const Test = () => {
const [name, setName] = useState('khalad')
const [age, setAge] = useState(18)
const handleInputChange = (e) => {
setName(e.target.value)
}
return(
<div>
<span>Name</span>
<input onChange={ handleInputChange } />
<span>{state.name}</span>
</div>
)
}
Upvotes: 0
Reputation: 10662
To make the input a controlled component, both value
and onChange
props should be assigned.
<input value={state.name} onChange={handleInputChange} />
handleInputChange
function can be improved to make sure that the state is updated immutably:
const handleInputChange = ({ target: { value } }) => {
setState(prevState => ({...prevState, name: value}));
}
Upvotes: 2