Дело в том, что setState меняет состояние не сразу после вызова (не синхронно), а когда-нибудь, поэтому неизвестно заранее, когда именно state будет реально изменени. Поэтому setState в качестве аргумента может принимать как объект так и функцию (коллбэк). И вот в этот самый коллбэк всегда передается текущее актуальное состояние. Поэтому твой код надо переписать как-то так:
export default class App extends Component {
state = {
items: []
};
add = (item) => {
this.setState((state) => ({
...state,
items: [...state.items, item]
}));
};
remove = (id) => {
this.setState((state) =>
return {
...state,
items: state.filter(item => item.id !== id),
}
);
};
updateItem = (id, item) => {
item.text = 'blabla';
this.remove(id);
this.add(item);
}
// Дальше остальные методы, рендер итд...
}
Другой вариант - отвязать методы add и remove от this.state, и передавать им state непосредственно. И этот вариант более правильный, т.к. он более явный, кроме того каждый вызов setState потенциально ведет к перерендеру, что нежелательно.
Поэтому как-то так:
export default class App extends Component {
state = {
items: []
};
add = (state, item) => ({
...state,
items: [...state.items, item]
});
remove = (state, id) => ({
...state,
items: state.filter(item => item.id !== id),
});
updateItem = (id, item) => {
item.text = 'blabla';
this.setState(state => this.add(this.remove(state, id), item));
}
// Дальше остальные методы, рендер итд...
}