

### 解決したいこと

Invalid Hook Call Warning を解決したいです。

railsのapiモードとreactを利用してポートフォリオを作ろうとしています。dockerを使って環境構築を行い、バックエンドとフロントエンドを分離して開発を行っています。

練習として、教材を使用して勉強中なのですが以下の３つのエラーが複数出てしまい、詰まってしまいました。

[code]

    ＃１つめ
    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.
    
    ＃２つめ
    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)
    
    ＃３つめ
    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.
    
[/code]

**App.tsx** (一部コメントアウトしています)

[code]

    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;
    
[/code]

**Foods.tsx** (残りのRestaurants,Ordersも同じように文字のみなので省略)

[code]

    export const Foods = () => {
        return (
            <>
                フード一覧
            </>
        )
    }
    
[/code]

### 自分の考察や試したこと

<https://ja.reactjs.org/warnings/invalid-hook-call-warning.html>

エラーを調べたところ公式ドキュメントに記載があったので引用。  
考えられる原因は以下の３つのようです。

### 1\. React と React DOM のバージョン不整合

公式サイトに以下の記述がありました。

> まだフックをサポートしてない 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のダウングレードを試みました。

しかし、以下のようになってしまいます。恐らく依存関係の問題だと考えられます。  
とりあえずここで一旦保留にしました。

[code]

    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
    
[/code]

### 2\. フックのルールへの違反

フックのルール違反についてですが、現時点でuseStateなどのフックを使用していないので恐らく当てはまらないと考えました。

### 3\. 重複した React のコピー

公式サイトに以下の記載がありました。

> フックが動作するためには、あなたのアプリケーションコード内で react インポート文を使った時に解決される react が、react-dom
> パッケージ内でインポートしている react と同じでなければなりません。
>
> これらの react のインポート文が別々のオブジェクトへと解決された場合、この警告が発生します。これは意図せず react パッケージの 2
> つのコピーをプロジェクトに含めてしまった場合に発生する可能性があります。
>
> パッケージ管理に Node を使っている場合は、プロジェクトフォルダ内で以下を実行することで確認できます：
>
> npm ls react  
>  もし React のコピーが 2 つ以上あった場合、その原因を突き止めて依存ツリーを修正する必要があります。例えばあなたの利用しているライブラリが
> react を peer dependency ではなく誤って dependency
> として使用しているのかもしれません。そのライブラリが修正されるまでは、Yarn resolutions が問題の回避策になりえます。

そのため、以下の通り実行しましたが、この結果を見ても重複は起きていないように思えます。

[code]

    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
    
[/code]

### その他

上に載せたApp.tsxのコメントアウトを外すとエラーになりますが、h2タグのみの場合やRouterを使わない場合には、エラーは発生せず、正常に画面に文字が出力されます。よって。BrowserRouterあたりに問題があると考えられます。ですが、ここからどうすればいいのか分からないです。

環境としては、  
・React18.1.0  
・Rails 6.1.6  
・Ruby 3.1.2  
・Dockerで環境構築を行った。

[Rails API × React ×
TypeScriptで作るシンプルなTodoアプリ](https://qiita.com/kazama1209/items/5c07d9a65ef07a02a4f5)

この記事の通りに行いました。

なにかしらアドバイスがあればよろしくお願いいたします。

### 追記

App.tsxの一部を編集しました。修正箇所のみ記述します。

[code]

    　　　<Routes>
              // 店舗一覧ページ
              <Route path="/restaurants" element={<Restaurants />} />
              // フード一覧ページ
              <Route path="/foods" element={<Foods />} />
              // 注文ページ
              <Route path="/orders" element={<Orders />} />
       　</Routes>
    
[/code]

### さらに追記

現在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つずつ存在することです。私のディレクトリ構造では

[code]

    /Playground-/backend
               |
               -/frontend-/node_modules
               |         |
       -d-c.yml(省略)     /-react-app-/node_modules
                         |           |
                         |           |-package.json
                         |
                         -Dockerfile,package.json,package-lock.json
    
[/code]

このようになっております。今までは仕様だと思っていたのですが、このディレクトリ構成はおかしいでしょうか？また、それぞれのpackage.json,node_modulesは中身がどれも違っています。  
・そもそもうまくreact-router-domなどのライブラリをインストールできていない  
これが原因かもしれませんが、エラーが出なかったので恐らく違うかと  
・Docker環境の外にNodeが入っているから？  
PC本体にはNodeの環境構築のみ行っております。1回だけcreate-react-
appで教材を使い、練習していた記憶があります。ですが、Docker環境とは関係ないはずなので違うかもしれません。

誠に勝手ながらマルチポストをさせていただきます。不快な思いをさせてしまったらすみません。

<https://teratail.com/questions/jywvvw4u9bai2y>


CC BY-SA 4.0
2022-05-18T13:01:29.343
88906
2023-08-07T02:00:35.073
2022-05-18T22:43:09.350
51193
51193
question
reactjs
Invalid Hook Call Warning を解決したい


解決しました。どうやらreact-router-domのインストール方法が悪かったようです。ここからは私の推測になるので間違っているかもしれません。  
私は

[code]

    docker-compose run front yarn create react-app react-app --template typescript
    
[/code]

のようにyarnを使ってcreate react-appしました。しかし、react-router-domを追加する際に誤ってnpmを使ってしまいました。

[code]

    docker-compose exec front npm install react-router-dom
    ↓修正
    docker-compose exec front yarn add react-router-dom
    ＊これでうまく動くようになりました。
    
[/code]

どうやらyarnでcreate-react-appした場合はyarn addで追加しないと予期せぬエラーになってしまうようです。  
誰かのお役に立てれば幸いです。ご協力いただきありがとうございました。


CC BY-SA 4.0
2022-05-19T00:43:31.440
88912
2022-05-19T00:43:31.440
51193
88906
answer