LaravelとReactを組み合わせた場合Vueの場合と違いルート要素を軒並み上書きしてしまうため
bladeの機能を犠牲にすべきか上のメニュー領域を犠牲にするかというジレンマがあったので二つのルート要素に対してReactDOMを配置してReact-Routerで通信する手段がないか模索したレポート
基本的には二つのルート要素というよりもBowserRouterでReact-Routerのページ割り当て(メニュー選択→コンテンツ領域切り替え)のようなことはできなくなっていてLinkでアドレスバーが変わってもRoute要素の表示は変わらなかった
まず最初に目を付けたのはReact-Router-Reduxだったが最新バージョンの関係か書いてある通りにやっても最初のデモが動かなかった
(githubの最新版のexampleもOSの関係かビルドでこけてた)
バージョンを揃える事でうまくいくかも知れないがいずれ廃れる旧バージョンで再現するのも癪だったのもあって他を探していたところ
@Anharu氏のReact Router v4とReduxを繋げるにはconnected-react-routerを使うのがおすすめだよ!というのがあったので試してみた
記事の省略箇所の関係か己の未熟さ故か上手くいかなかったので本家からソースを取得しexample(connected-react-router-master/examples/basic)をためしてみた
幸いyarnコマンドで問題なく依存関係を解決できyarn startでうまく起動した
ソースを加工し二つのルート要素にReactDOMを割り当ててみたところ無事二つのDOM領域が同期して表示切替された
これを元に最小構成になるように切り出しをしたところ以下のようになった
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Minimal Hot Reload</title>
</head>
<body>
<div id="menu"></div>
<hr />
<div id="react-root"></div>
<script src="/dist/bundle.js"></script>
</body>
</html>
import React from 'react'
import ReactDOM from 'react-dom'
import { createStore, combineReducers } from 'redux'
import { Provider } from 'react-redux'
import { Link, Route, Switch } from 'react-router-dom'
import { connectRouter, ConnectedRouter } from 'connected-react-router'
import { createBrowserHistory } from 'history'
const history = createBrowserHistory()
const rootReducer = (history) => combineReducers({ router: connectRouter(history) })
const store = createStore(rootReducer(history))
const Home = () => (<div>Home</div>)
const Content2 = () => (<div>Content2</div>)
const Content3 = () => (<div>Content3</div>)
const NoMatch = () => (<div>NoMatch</div>)
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<div>
<Link to="/">Home</Link>
<Link to="/content2">Content2</Link>
<Link to="/content3">Content3</Link>
</div>
</ConnectedRouter>
</Provider>
,document.getElementById('menu')
)
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/content2" component={Content2} />
<Route path="/content3" component={Content3} />
<Route component={NoMatch} />
</Switch>
</ConnectedRouter>
</Provider>
,document.getElementById('react-root')
)
確認用の最小構成としてはこれで動きますが拡張性を考えるなら元のexampleのディレクトリ構成を活かした方がいいと思います。