jQuery "видит" весь DOM целиком. И манипулирует DOM-ом, доступ к которому предоставляет браузер. Но можно и по-другому.
Давайте рассмотрим такую архитектуру, в которой все компоненты связаны между собой древовидно. То есть, отдельно взятый компонент может общаться со своими дочерними и со своим родительским. Если нужно, чтобы между собой пообщались два компонента в разных ветках, то в конце концов их общение происходит через общего предка. Такой подход вполне согласуется с древовидной структурой HTML.
Затем отделим состояние от поведения и представления. Состояние можно описать статической структурой данных, JSON-ом, например. А поведение - это чистая функция, из предыдущего состояния и некоего события (действия) делающая следующее состояние. Представление же "знает", как визуализировать состояние. Можно этот принцип воспроизвести от самых мелких компонент (не имеющих потомков) в нашем дереве и до корня. Тогда весь жизненный цикл приложения можно изобразить как цепочку состояний от некоего начального и до текущего, ведомую событиями (действиями).
Для того, чтобы это всё отобразить, не обязательно в ходе вычисления следующего состояния (или представления) сразу манипулировать DOM-ом. Можно построить из состояния и его представления фрагмент DOM-а, каким он должен получиться. А потом вычислить diff между этим построенным фрагментом (виртуальным DOM-ом) и реальным браузерным. И этот diff применить к реальному DOMу. Один раз. Получится быстро.
Насколько мне известно (поправьте, если это не так), Redux заимствован из Elm-а. Elm - это экосистема и функциональный язык, компилируемый в JS, сделанный для того, чтобы фронтэнд можно было разрабатывать удобно, быстро и без runtime-ошибок. По синтаксису - это адаптация Haskell-a. Ключевым элементом Elm-а является как раз вот эта самая архитектура. Советую подробнее почитать в первоисточнике.
https://guide.elm-lang.org/architecture/
Кроме упомянутых особенностей эта архитектура также позволяет выполнять так называемую time-travelling отладку. Поскольку каждое состояние и каждое событие по пути от исходного до текущего можно залогировать и воспроизвести (ведь функция, вычисляющая следующее состояние у нас чистая).
С точки зрения функционального программирования, при таком подходе текущее состояние является результатом функции leftFold, применённой к исходному состоянию, последовательности событий (действий), приводящих к текущему и функции, умеющей вычислять следующее состояние.