состояние реакции не обновляется при изменении ввода

#reactjs #state #use-state

Вопрос:

У меня есть массив объектов в крючке useState, с помощью которого я визуализировал входные элементы. Состояние не обновляется при изменении входного элемента.

Вот Мой Код.

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 функция

 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
    })
}
 

Комментарии:

1. попробуйте переместить функцию updateAnswerValue в свой компонент, вам не нужно импортировать ее и отправлять функцию setState в качестве опоры или создавать другую функцию в своем компоненте, которая использует установщик состояний setProceduralAnswers, и передавать ее в качестве опоры функции обратного вызова.

2. Я создал этот пример, надеюсь, это поможет … codesandbox.io/s/affectionate-silence-rbbkm?file=/src/…

Ответ №1:

Я думаю, что это не работает, потому что следующее состояние имеет ту же ссылку, что и предыдущее состояние, вы изменяете значение только одного элемента. Хук useState вызовет повторное отправление, если ссылка изменится. Поэтому ваш обратный звонок должен выглядеть так.

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

Ответ №2:

попробуйте это

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

Комментарии:

1. это не ответило на мой вопрос, но мне понравилась простота кода.

2. вы фильтровали новое состояние и возвращали новое состояние, функция фильтра не изменяет значение состояния, она возвращает массив, поэтому вы должны возвращать сохраненное значение, а не новое состояние

Ответ №3:

Вы возвращаете новое состояние вместо текущего ответа.

Ответ №4:

Во-первых, если вы пытаетесь найти только один предмет [].find , не используйте filter его .

var newState = state; не дает вам новую копию, измените новое состояние, и вы тоже будете менять состояние, вам нужно это сделать var newState = [...state]; (предупреждение: это только поверхностная копия).

Похоже, вы думаете currentAnswer newState , что каким-то образом делитесь ссылкой, а это не так. Всякий раз, когда вы запускаете map , find , filter или reduce вы получаете свежую копию массива, чтобы не было связи между 2.

Хорошая ставка здесь-просто нанести на карту штат

 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;
    }));
};