Декларативность это не цель. Главное чтобы было быстро добавлять в проекте новые фичи или менять существующие не зарываясь в проблемы ранее добавленных фич. Еще можно добавить пункт про читаемость кода и понимание что вообще происходит в приложении но это уже следствие требования "быстрого добавления/изменения фич"
И вот при всем этом "декларативность" или какой-то способ описания процессов который предлагает эффектор на мой взгляд намного хуже решает задачу понимания "что вообще происходит". На мой взгляд изменение состояние в обработчике клика намного понятнее и удобнее
<button onClick={()=>{
AppState.todos.push({id: ..., text: AppState.newTodoText, completed: false});
AppState.newTodoText = "";
actualizeDOM();
}}>
add todo
</button>
чем то что предлагает эффектор.
Почему это удобно - не нужно бегать по файлам приложения или по различным indirect-вызовам. Вот кнопка и вот тебе сразу логика которая меняет состояние. Никаких асинхронных процессов и т.д все что касается обработки кнопки - все находится тут же в обработчике клика
А то что это смешано с версткой, то это на мой взгляд вполне правильно - ui же определяет фичи. Сегодня есть кнопка а завтра дизайнер/заказчик решил ее убрать или поменять логику работы или вообще концепцию всего приложения. Такой себе "ui-driven development" получается. Если мы будем наворачивать абстракции - когда кнопка вызывает там какое-то событие эффектора которое описано в другом файле а это событие обрабатывается кодом в третьем файле то замучаешься прыгать по коду (и чистить каждый раз эти события/редюсеры когда удаляется/меняется логика кнопки)