Есть опыт с Vue в похожей ситуации, суть та же самая.
Где-то в шаблонах формируется контейнер для компонента, в атрибутах которого передаются пропсы для компонента:
<div
data-component="ComponentName"
data-component-props='{ "id": "123", "foo": "bar" }'
>
</div>
Где-то в Component.js происходит инициализация компонента:
// псевдо-код
const el = получили элемент с data-component="ComponentName" или с каким-то id и т.д.
const props = спарсили пропсы из атрибута
const app = отрендерили React-компонент в этом жлементе передав ему пропсы
С Vue ранее еще пробовали инициализировать приложение прямо на body и использовать кастомные теги для компонентов, но выходило хуже, с пропсами было неудобно.
Из известных крупных сайтов Lamoda например делает что-то подобное. Поищите по исходному коду страницы товара
<div class="vue-widget">
С SEO быть или никак, или заполняя будущий контейнер для компонента голым сеошным текстом и потом его замещая рендером компонента. Скорее всего, реакт вы будете использовать для динамических вещей - формы, конструкторы, корзина и т.д., которым сео не нужно.
По опыту использования такого подхода на нескольких средних проектах могу сказать, что подход рабочий. Писать динамические компоненты на Vue гораздо удобнее. Мы написали что-то вроде недо-микро-фреймворка для удобного биндинга vue и не-vue компонентов
https://github.com/interfacesdev/nospa Внутри у себя используем, но рекомендовать к вашему продакшену не могу - документация не закончена, поддержки нет, на гитхаб пока просто выдернули актуальную версию с прошлого проекта. Может когда-то руки дойдут заняться плотнее.
А в целом значительно удобнее писать фронт полностью на Vue/React, используя, например, Next/Nuxt для рендеринга и все эти по сути костыли просто от безысходности :( Но это уже тема отдельной дискуссии.