Home > Enterprise >  react state not updating on input change
react state not updating on input change

Time:10-07

I have an array of objects in a useState hook with which i rendered input elements. The state doesn't get updated when the input element changes.

Here Is My Code.

ProceduralResponseAnswerCreate Component

const ProceduralResponseAnswerCreate = () => {
    const [proceduralAnswers, setProceduralAnswers] = useState([{ "value": "One" }, { "value": "two" }])
    return <>
        <ol>
            {proceduralAnswers.map((answer, answer_index) => <input key={answer_index} style={inputStyle} onChange={(event) => updateAnswerValue({ event, setProceduralAnswers, answer_index })} value={answer.value} />)}
        </ol>
    </>
}

export default ProceduralResponseAnswerCreate

updateAnswerValue function

export const updateAnswerValue = ({ event, setProceduralAnswers, answer_index }) => {

    setProceduralAnswers(state => {
        var newState = state;
        var currentAnswer = newState.filter((state_1, index) => index === answer_index)[0]
        currentAnswer.value = event.target.value
        return newState
    })
}

CodePudding user response:

try this

export const updateAnswerValue = ({ event, setProceduralAnswers, answer_index }) => {
    
        setProceduralAnswers(state => {
            var newState = state;
            newState[answer_index].value = event.target.value
            return newState
        })
    }

CodePudding user response:

I think it doesn't work because the next state has the same Reference as the previous state, you only change the value of one element. The useState hook will trigger a rerender, if the reference changes. So your Callback must look like this.

setProceduralAnswers(state => {
    let newState = state;
    let currentAnswer = newState.filter((state_1, index) => index === answer_index)[0]
    currentAnswer.value = event.target.value
    return [...newState]
})

CodePudding user response:

You are returning the newState instead of the currentAnswer.

CodePudding user response:

First off, if you're only trying to find one item use [].find not filter.

var newState = state; does not give you a fresh copy, change newState, and you'll be changing state too, you need to do var newState = [...state]; (warning: this is a shallow copy only).

It looks like you think currentAnswer shares a reference with newState in some way, which it doesn't. Whenever you run map, find, filter or reduce you're getting a fresh copy of the array so there will not be a link between the 2.

A good bet here is to just map the state

export const updateAnswerValue = ({
    event,
    setProceduralAnswers,
    answer_index
}) => {
    setProceduralAnswers((state) => state.map((state_1, index) => {
        if (index === answer_index) {
            return {
                ...state_1,
                value: event.target.value
            }
        }

        return state_1;
    }));
};
  • Related