【react-router@3.x→4.x】動かない。。アップデートで困っている人が読む記事(how to update react-router3.x vs 4.x)
最近react-routerを3から4に変更したのですが、色々チェンジがあって苦戦しました。
react-routerをあまり触る機会がなかった自分はとりあえずreact-router@1.0.0から2.0.0、3.0.0とあげていき、注意を払っていきましたが、3.0.0から4にあげた瞬間
大変なことになりました。
また関連してこのような記事を書きました
【react-router@3.x→4.x】動かない。。アップデートで困っている人が読む記事(props(history, location, match等)をRouteから渡したい!!)
出会ったエラー達
1.Uncaught TypeError: Cannot read property 'pathname' of undefined
2.Warning: Failed prop type: Invalid prop `history` of type `function` supplied to `Router`, expected `object`.
3.Uncaught Error: A <Router> may have only one child element
4.Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of `App`.
5.Warning: You should not use <Route component> and <Route children> in the same route; <Route children> will be ignored
そこで、今担当しているサイトのrouter構造に似せた「最小のrouter周り」を実装して、一つ一つどこがどうエラー出しているのか探り、調べながら解決していきました。
その際記事があまりなくて困りましたので、同じ状況の方に
自分が変更した箇所をわかりやすく伝えようと思います。
参照リンク
公式
https://reacttraining.com/react-router/web/guides/quick-start
古いやつだけど理解するのに役立つ
https://github.com/reactjs/react-router-tutorial/tree/master/lessons
簡単なsample作ったり
Using Webpack and React-router to improve performance with lazy loading
この際理解を深める
Beginner’s Guide to React Router
react-router-domのdoc。apiかguideから。(これもなかなか見つからないとこに置いてある。。)
https://github.com/ReactTraining/react-router/tree/master/packages/react-router-dom/docs
実際の作業
react-router@3.x→4.xのエラー対応
1.Uncaught TypeError: Cannot read property 'pathname' of undefined
上記はpathnameが未定義と出ていますが、Uncaught TypeError: Cannot read property 'location' of undefinedと出る場合もあります。
historyから読み込んでいるBrowserRouterに原因があります。
下のエラーと同じ対応をしました。
2.Warning: Failed prop type: Invalid prop `history` of type `function` supplied to `Router`, expected `object`.
history関連。上の2つは下のように変更することで変わります
ここに書きました。
これを
ここを見ると
https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js
react-router-dom内のBrowserRouterがhistoryを使っています。
npmのhistoryやreact-routerからcreateHistoryをimportして独自に実装するのをやめます。
4.xからは提供するBrowserRouterをreact-router-domからエイリアスとしてimportするようにすると消えます。
3.Uncaught Error: A <Router> may have only one child element
これは子供のコンポーネントをまとめて返しなさいということでした ここ を参照して とりあえずdivで包んでおいてください。
エラーが変わることを確認してください。
4.Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of `App`.
これが出たら試してもらいたいことがあります。 問題を切り分けました。
どこかのコンポーネントがexportされていないか、もしくはその呼び出し方に問題があるようです。 この場合最後の'App'と言われていますのでそこがうまいこと行っていません このように
中にあるやつごっそり消して(あとで「ctr-z」)みて適当に打った文字列が表示されて、エラーがなくなっていることを確認してください。 言われていることは
要素タイプが無効です:文字列(組み込みコンポーネントの場合)またはクラス/関数(複合コンポーネントの場合)が必要ですが、未定義です。 コンポーネントが定義されているファイルからコンポーネントをエクスポートするのを忘れた可能性があります。 `App`のレンダリングメソッドをチェックしてください。
なので独自に定義したコンポーネントとして渡す必要があります。(もしくは渡されてきていない) 該当のComponentが(上記の場合App)が正しくexportされているかもそうなのですが、 v4.0.0では使われていないComponentを呼び出している可能性があります。 それが該当のComponentからで、 レンダリングされているComponentもチェックしてみてください。 自分の場合 <IndexRouter component={Hoge}>を削除したらいけました。 これ、結構苦戦しました。。
IndexRouterの代わりにSwitchを実装します。
import { Switch } from 'react-router'
として
[javascript]
<Switch>
<Route exact path="/" component={Home}/>
<Route path='/about'component={About} />
<Route path='/feature' component={Features} />
<Route component={NoMatch}/>
</Switch>
[/javascript]
このようにします。
<Route exact path="/" component={Home}/>
remove <IndexRouter component={Hoge}>
use Switch instead of IndexRouter
5.Warning: You should not use <Route component> and <Route children> in the same route; <Route children> will be ignored
Routeを同階層でネストすると言われます。 どういう時言われるかというと Router同士でネスとして {this.props.child}でレンダリング、親Routeから呼んでいる時です。 そこに書いてある通りネストされたRouteの子Routeは無視されます。 ここをみてください Routeでネストしています。 それを ここにある ようにネストした親の中から呼んでください。(これがベストプラクティスではないと思いますがWarningは消えます。環境に合わせてください) 以上ですが、 またエラーと出会ったらここのページ更新していきます。。 今回の変更箇所概要。
以上です。
もし周りでreact-router3.xから4.xに移行する人が困っていたらこのページ教えてあげてください。
追記 2017/4/13
historyからのpropsをRuteから渡したい方へ。こちら書きました。
【react-router@3.x→4.x】動かない。。アップデートで困っている人が読む記事(props(history, location, match等)をRouteから渡したい!!)
こちらのページは随時更新していきますのでブックマークお願いします!!
では〜〜