Проблема в том, что вы напрямую мутируете объект состояния:
if(selectedOptions[selectedOptionId]){
delete selectedOptions[selectedOptionId];
} else {
selectedOptions[selectedOptionId] = {}
}
onChange(selectedOptions);
В обоих случаях вы изменяете объект состояния, а затем устанавливаете его как самого себя, поэтому, естественно, useEffect
не будет срабатывать как установщик не внес никаких фактических изменений. Вы должны быть осторожны, делая это в React, так как это простой способ получить устаревшие значения. Повторная отрисовка запускается только тогда, когда есть разница между текущим состоянием и значением, переданным установщиком, а не всякий раз, когда значения состояния меняются по какой-либо причине.
В комментарии предлагается использовать распространение - ...
- деструктурировать объект состояния, чтобы вы могли установить его как самого себя, но мне это кажется чем-то вроде анти-паттерна, тем более что он оставляет мутацию состояния на месте. Если вы хотите удалить запись из объекта состояния, общий подход будет заключаться в том, чтобы сначала клонировать объект, изменить клон, а затем установить это как новое состояние:
const clone = Object.assign({}, selectedOptions);
if(clone[selectedOptionId]){
delete clone[selectedOptionId];
} else {
clone[selectedOptionId] = {}
};
onChange(clone);
Однако небольшое предостережение, любые вложенные объекты внутри этого объекта сохранят свои ссылки на исходное состояние и все равно могут его видоизменить. Вам также придется клонировать эти вложенные объекты, чтобы избежать проблемы.