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