Использование React Router и React.rb
Я пытаюсь использовать React Router из реакции.rb. Я начал использовать Gem реактора-маршрутизатора, но Gem работает только с React Router < 1, и я использую React Router 2.4.0, и его API совершенно другой.
За последние недели я использовал несколько подходов, чтобы заставить это работать, но ни один из подходов не был правильным, каждый из которых имел свою собственную ошибку.
Пожалуйста, кто-нибудь направит меня в правильном направлении, так как у меня нет выбора.
С точки зрения настройки, я использую Webpack, чтобы требовать React и React Router, поэтому application.js, который внедряется в Webpack, выглядит следующим образом:
React = require('react')
ReactDOM = require('react-dom')
_reactRouter = require('react-router')
Подход 1 - создайте Маршрутизатор как собственный JS и вызовите ReactDOM.render для рендеринга маршрутизатора при рендеринге компонента верхнего уровня
before_mount do
@admin_members = React::API::create_native_react_class(Components::Company::AdminMember)
@squad_index = React::API::create_native_react_class(Components::Squad::Index)
@squad_show = React::API::create_native_react_class(Components::Squad::Show)
@tribe_index = React::API::create_native_react_class(Components::Tribe::Index)
@tribe_show = React::API::create_native_react_class(Components::Tribe::Show)
end
и затем рендеринг маршрутизатора в div в after_mount:
after_mount do
`ReactDOM.render(React.createElement(
_reactRouter.Router,
{ history: _reactRouter.browserHistory },
React.createElement(_reactRouter.Route, { path: "admin/members", component: #{@admin_members} }),
React.createElement(_reactRouter.Route, { path: "/squads", component: #{@squad_index} }),
React.createElement(_reactRouter.Route, { path: "/squads/:squad_id", component: #{@squad_show} }),
React.createElement(_reactRouter.Route, { path: "/tribes", component: #{@tribe_index} }),
React.createElement(_reactRouter.Route, { path: "/tribes/:tribe_id", component: #{@tribe_show} })
), document.getElementById('bh_router_div')
);`
end
Этот подход, хотя и не очень, кажется, работает в том, что маршрутизатор создан и функционирует, как ожидалось. URL или /tribe/22 загрузит правильный компонент TribeShow и передаст правильный идентификатор компоненту.
Проблема, с которой я сталкиваюсь при таком подходе, заключается в том, что когда дело доходит до создания ссылки, так как компонент ссылки не использует тот же контекст, что и маршрутизатор. Я полагаю, что это связано с тем, что ReactDOM.render вызывается один раз при помощи response-rb, а затем еще раз в коде выше. Это создает два корневых компонента на странице (TopLevelRailsComponent) и (ReactRouter).
Ссылка создана таким образом:
class MyRouter < React::NativeLibrary
imports '_reactRouter'
end
И затем используется в методе рендеринга компонентов следующим образом:
MyRouter.Link({to: "/admin/members"}) { "and here is the link"}
Ссылка отображается, но нажатие на нее дает следующее предупреждение и не приводит к переходу к компоненту:
Uncaught TypeError: Cannot read property 'push' of undefined
Глядя на свойства компонента Link, я вижу, что контекст нулевой, и я считаю, что именно поэтому. Кажется, что ссылка рисуется вне контекста маршрутизатора.
Подход 2 - используйте API реагирования-рб для рендеринга маршрутизатора, чтобы ReactDOM.render не вызывался дважды на странице
Это кажется лучшим подходом, но до сих пор мне не удалось заставить это работать должным образом.
Основываясь на том, как я создаю ссылку выше, в методе рендеринга компонента:
MyRouter.Router({history: `_reactRouter.browserHistory` },
MyRouter.Route({ path: "/admin/members", component: @admin_members})
) {}
Но я получаю следующее предупреждение, и страница не отображается:
Uncaught Invariant Violation: <Route> elements are for router configuration only and should not be rendered
Подход 3 - создайте компонент Route в нативном JS, чтобы он не отображался:
`var AppRoutes = React.createElement(_reactRouter.Route, { path: "/admin/members", component: #{@admin_members} });`
MyRouter.Router({history: `_reactRouter.browserHistory` },
`AppRoutes`
) {}
Это проходит мимо предыдущей ошибки, НО маршрутизатор фактически не маршрутизирует, и я получаю следующее предупреждение (и компонент не рендерится):
Warning: [react-router] Location "/admin/members" did not match any routes
history: Как примечание, в обоих приведенных выше примерах я попытался установить историю как таковую:
MyRouter.Router({history: MyRouter.browserHistroy },
`AppRoutes`
) {}
Но я получаю предупреждение о предоставлении устаревшей истории, и когда я проверяю значение, оно равно нулю. С помощью _reactRouter.browserHistory
проходит мимо этого предупреждения. Я не уверен, имеет ли это отношение к тому факту, что маршрутизатор не маршрутизирует или нет.
Я был бы очень признателен за любую помощь или направить на это. Было бы очень даже полезно узнать, какой из подходов является правильным, и любые намеки относительно того, как действовать дальше.
1 ответ
Это было решено в ветке V2.4.0 реактивного маршрутизатора https://github.com/reactrb/reactrb-router/tree/v2-4-0
Также обратите внимание на новый DSL