Начнем с того, почему так происходит. ref срабатывает каждый раз, когда происходит рендер. Поскольку модалка использует setState, которая вызывает render, который запускает функцию в ref, в массив каждый раз попадает все больше ссылок, с каждым открытием\закрытием модалки. Иногда в ref может быть null, из-за инлайн функции
Подробнее.
Однако такой подход в принципе не правильный.
Для управлением состоянием чекбокса, использование ref не принято. Использование ref в React в принципе нежно использовать не очень часто. Правильный подход - использование props: checked\defaultChecked и onChange
Формы
Вообще, состояние должно быть в реакте, а реакт сам применяет его на DOM, в это его суть.
Правильный вариант - положить состояние чекбоксов в стейт, в виде массива или Set'а.
state = {
values: [false, false, false], // Изначально все 3 чекбокса выключены
};
onToggleCheckbox = (checked, index) => {
this.setState(({ values: prevValues }) => {
const newValues = [...prevValues]; // меняем состояние нужного чекбокса по индексу
newValues[index] = checked;
return {
value: newValues,
};
});
};
onToggleAll = checked => {
this.setState(({ values }) => ({
values: values.map(() => checked),
}));
};
Тогда отрисовка чекбоксов:
<div>
{this.props.checked.map((value, index) => (
<input
type="checkbox"
checked={value}
key={index}
onChange={event => this.props.onToggle(event, index)}
/>
))}
</div>
Состояние чекбокса который переключает все остальный вычислимое:
<input type="checkbox" checked={this.props.values.every(value => value)} onChange={event => this.props.onToggleAll(event.target.checked)} />