解決したいこと
Invalid Hook Call Warning を解決したいです。
railsのapiモードとreactを利用してポートフォリオを作ろうとしている者です。dockerを使って環境構築を行い、バックエンドとフロントエンドを分離して開発を行っています。練習として、教材を使用して勉強中なのですが以下のエラーが出てしまい、詰まってしまいました。
#1つめ react.development.js:207 Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. #2つめ react.development.js:1628 Uncaught TypeError: Cannot read properties of null (reading 'useRef') at useRef (react.development.js:1628:1) at BrowserRouter (index.tsx:151:1) at renderWithHooks (react-dom.development.js:16175:1) at mountIndeterminateComponent (react-dom.development.js:20913:1) at beginWork (react-dom.development.js:22416:1) at HTMLUnknownElement.callCallback (react-dom.development.js:4161:1) at Object.invokeGuardedCallbackDev (react-dom.development.js:4210:1) at invokeGuardedCallback (react-dom.development.js:4274:1) at beginWork$1 (react-dom.development.js:27405:1) at performUnitOfWork (react-dom.development.js:26513:1) #3つめ react-dom.development.js:18572 The above error occurred in the <BrowserRouter> component: at BrowserRouter (http://localhost:3000/static/js/bundle.js:1198:5) at App Consider adding an error boundary to your tree to customize error handling behavior. Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
上の3種類のエラーが複数出ている状況です。
App.tsx *一部コメントアウトしています
import React from 'react'; import './App.css'; import { BrowserRouter, Routes, Route, } from "react-router-dom"; // components import { Restaurants } from './containers/Restaurants'; import { Foods } from './containers/Foods'; import { Orders } from './containers/Orders'; function App() { return ( // <BrowserRouter> // <Routes> // // 店舗一覧ページ // <Route path="/restaurants"> // <Restaurants /> // </Route> // // フード一覧ページ // <Route path="/foods"> // <Foods /> // </Route> // // 注文ページ // <Route path="/orders"> // <Orders /> // </Route> // </Routes> // </BrowserRouter> <h2>a</h2> ); } export default App;
Foods.tsx *残りのRestaurants,Ordersも同じように文字のみなので省略
export const Foods = () => { return ( <> フード一覧 </> ) }
自分の考察や試したこと
https://ja.reactjs.org/warnings/invalid-hook-call-warning.html
エラーを調べたところ公式ドキュメントに記載があったので引用
考えられる原因は以下の3つのようです
1 React と React DOM のバージョン不整合
2 フックのルールへの違反
3 重複した React のコピー
1について
公式サイトの記述に「まだフックをサポートしてない react-dom (< 16.8.0) や react-native (< 0.60) を利用しているのかもしれません。アプリケーションフォルダで npm ls react-dom か npm ls react-native を実行して、どのバージョンを使っているのかを確認できます。もしも 2 つ以上出てきた場合は、それも問題になりえます(後述)。」とありました。確かに今回は私が使っているreact-domは18.1.0なのでこれが原因かと考え、react-domのダウングレードを試みました。しかし、
senseiy@senseIY-wsl:~/Practice/Rea-pra/playground$ docker-compose exec front npm install react-dom@16.7.0 npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: undefined@undefined npm ERR! Found: react-dom@18.1.0 npm ERR! node_modules/react-dom npm ERR! peer react-dom@">=16.8" from react-router-dom@6.3.0 npm ERR! node_modules/react-router-dom npm ERR! react-router-dom@"^6.3.0" from the root project npm ERR! react-dom@"16.7.0" from the root project npm ERR! npm ERR! Could not resolve dependency: npm ERR! react-dom@"16.7.0" from the root project npm ERR! npm ERR! Conflicting peer dependency: react@16.14.0 npm ERR! node_modules/react npm ERR! peer react@"^16.0.0" from react-dom@16.7.0 npm ERR! node_modules/react-dom npm ERR! react-dom@"16.7.0" from the root project npm ERR! npm ERR! Fix the upstream dependency conflict, or retry npm ERR! this command with --force, or --legacy-peer-deps npm ERR! to accept an incorrect (and potentially broken) dependency resolution. npm ERR! npm ERR! See /root/.npm/eresolve-report.txt for a full report. npm ERR! A complete log of this run can be found in: npm ERR! /root/.npm/_logs/2022-05-18T06_14_24_182Z-debug-0.log
このようになってしまいます。恐らく依存関係の問題だと考えられます。とりあえずここで一旦保留しました。
2について
フックのルール違反についてですが、現時点でuseStateなどのフックを使用していないので恐らく当てはまらないと考えました。
3について
公式サイトに「フックが動作するためには、あなたのアプリケーションコード内で react インポート文を使った時に解決される react が、react-dom パッケージ内でインポートしている react と同じでなければなりません。
これらの react のインポート文が別々のオブジェクトへと解決された場合、この警告が発生します。これは意図せず react パッケージの 2 つのコピーをプロジェクトに含めてしまった場合に発生する可能性があります。
パッケージ管理に Node を使っている場合は、プロジェクトフォルダ内で以下を実行することで確認できます:
npm ls react
もし React のコピーが 2 つ以上あった場合、その原因を突き止めて依存ツリーを修正する必要があります。例えばあなたの利用しているライブラリが react を peer dependency ではなく誤って dependency として使用しているのかもしれません。そのライブラリが修正されるまでは、Yarn resolutions が問題の回避策になりえます。」
とあったので以下を実行しました。
senseiy@senseIY-wsl:~/Practice/Rea-pra/playground$ docker-compose exec front npm ls react app@ /usr/src/app `-- react-router-dom@6.3.0 +-- react-dom@18.1.0 | `-- react@18.1.0 deduped +-- react-router@6.3.0 | `-- react@18.1.0 deduped `-- react@18.1.0
ですが、この結果を見ても重複は起きていないように思えます。
その他
上に載せたApp.tsxのコメントアウトを外すとエラーになりますが、h2タグのみの場合やRouterを使わない場合には、エラーは発生せず、正常に画面に文字が出力されます。よって。BrowserRouterあたりに問題があると考えられます。ですが、ここからどうすればいいのか分からないです。
環境としては、
・React18.1.0
・Rails 6.1.6
・Ruby 3.1.2
・Dockerで環境構築を行った。https://qiita.com/kazama1209/items/5c07d9a65ef07a02a4f5#%E5%AF%BE%E8%B1%A1%E8%AA%AD%E8%80%85
この記事の通りに行いました。
なにかしらアドバイスがあればよろしくお願いいたします。
追記
App.tsxの一部を編集しました。修正箇所のみ記述します。
<Routes> // 店舗一覧ページ <Route path="/restaurants" element={<Restaurants />} /> // フード一覧ページ <Route path="/foods" element={<Foods />} /> // 注文ページ <Route path="/orders" element={<Orders />} /> </Routes>
さらに追記
現在CodeSandboxで動作確認(正確にはReact TypeScriptのみでrailsはないが)をしたところ、正常に動作しました。バージョンも
react
18.1.0
react-dom
18.1.0
react-router-dom
6.3.0
react-scripts
5.0.1
のようにエラーが出ているDocker環境のものと同じにしています。
よって、React側のバージョンの不整合、記述ミスはエラーの原因ではないと考えています。
あり得るとすれば、
・そもそもディレクトリ構成が間違っている?
気になったのがpackage.jsonファイルとmode_modulesがそれぞれ2つずつ存在することです。私のディレクトリ構造では
/Playground-/backend | -/frontend-/node_modules | | -d-c.yml(省略) /-react-app-/node_modules | | | |-package.json | -Dockerfile,package.json,package-lock.json
このようになっております。今までは仕様だと思っていたのですが、このディレクトリ構成はおかしいでしょうか?また、それぞれのpackage.json,node_modulesは中身がどれも違っています。
・そもそもうまくreact-router-domなどのライブラリをインストールできていない
これが原因かもしれませんが、エラーが出なかったので恐らく違うかと
・Docker環境の外にNodeが入っているから?
PC本体にはNodeの環境構築のみ行っております。1回だけcreate-react-appで教材を使い、練習していた記憶があります。ですが、Docker環境とは関係ないはずなので違うかもしれません。
注意 誠に勝手ながらマルチポストをさせていただきます。不快な思いをさせてしまったらすみません。
回答1件