Khaled Attia
Khaled Attia

Reputation: 15

react state is not updating the UI

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

Answers (3)

Dawood Ahmad
Dawood Ahmad

Reputation: 474

simply do it like this, it will work

const handleInputChange = (e) => {
       
setState({...state, name: e.target.value})
        
}

Upvotes: 0

Plargato
Plargato

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

Ramesh Reddy
Ramesh Reddy

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

Related Questions