Обновления состояний асинхронные. Повторно делая
setState( [...state, {name, value}]);
, вы несколько раз используете оригинальный state
, а не новый.
В идеале, не вызывайте setState
несколько раз, не позволяя компоненту сделайте перерыв между ними, сделайте что-то вроде этого:
const addAll = (entries) => {
setState([...state, ...entries]);
};
addAll(array);
Но если вам нужно повторно вызывать свой установщик состояний, используйте форму обратного вызова, чтобы вы всегда использовали текущее состояние, а не устаревшее состояние :
setState(currentState => [...currentState, {name, value}]);
В комментарии вы сказали:
setState(currentState => ({...currentState, [name]: value}))
Но для объекта это не работает
Это делает этот код выглядит совершенно правильно, если вы пытаетесь установить свойство, имя которого в name
, равно value
:
const { useState } = React;
const Example = () => {
const [state, setState] = useState({
a: 1,
b: 2
});
const updateProperty = (name, value) => {
setState(currentState => ({...currentState, [name]: value}));
};
const addA = () => {
updateProperty("a", state.a + 1);
};
const addB = () => {
updateProperty("b", state.b + 1);
};
const addC = () => {
updateProperty("c", (state.c || 0) + 1);
};
return (
<div>
<div>a = {state.a}, b = {state.b}, c = {state.c}</div>
<input type="button" value="Inc A" onClick={addA} />
<input type="button" value="Inc B" onClick={addB} />
<input type="button" value="Create/Inc C" onClick={addC} />
</div>
);
};
ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Однако я не рекомендую это делать. С помощью крючков лучше хранить данные о состоянии отдельно:
const { useState } = React;
const Example = () => {
const [a, setA] = useState(1);
const [b, setB] = useState(2);
const [c, setC] = useState(undefined);
const addA = () => {
setA(a => a + 1);
};
const addB = () => {
setB(b => b + 1);
};
const addC = () => {
setC(c => (c || 0) + 1);
};
return (
<div>
<div>a = {a}, b = {b}, c = {c}</div>
<input type="button" value="Inc A" onClick={addA} />
<input type="button" value="Inc B" onClick={addB} />
<input type="button" value="Create/Inc C" onClick={addC} />
</div>
);
};
ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>