npm-link 與 Invalid hook call 錯誤

andyyou
3 min readMar 2, 2020

一切始於開發 React Hook 函式庫的過程中遭遇了下面的錯誤:

Error: 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://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

問題

為什麼會遇到這個問題?如果您是一個函式庫的作者我想在本地開發的情況下使用到 npm link 時您可能就會遇到這個問題。

讓我們先從 Node.js 的模組載入開始,Node.js 的載入流程非常單純,當我們使用 require 的時候

  1. 如果我們載入的是核心模組例如 http ,那麼直接載入核心模組的內容。
  2. 如果是相對路徑,則載入相對路徑
  3. 假如上述都不符合,則搜尋該目錄下的 node_modules 如果還是沒有則遞迴往上層的 node_modules 搜尋直到系統的根目錄。

鋪陳這段是為了後面理解為什麼 React 說我們使用了兩個版本的 React。

我們的需求是:我們在本地開發一個函式庫,想要在本地的應用程式中直接使用並調整 — 具體步驟如下

# 1. 為 package 建立連結 
$ cd [YOUR_PACKAGE]
$ npm link
# 連結會建立在 {PREFIX}/lib/node_modules
$ npm prefix -g # 查詢 PREFIX # 2.到專案目錄下
$ npm link [YOUR_PACKAGE]
# 補充:
# 您也可以直接 npm link [PACKAGE_PATH] npm 會幫你執行上面兩個步驟
# 查詢現有的連結
$ npm ls -g --depth=0 --link=true
# 查詢專案中使用的連結
$ ls -l node_modules | grep ^l

npm-install v.s. npm -link

您可能會問 npm install 也可以直接安裝本地 package 為什麼要用 npm link 但對於開發來說最大的差異是 npm install 是複製目錄到 node_modules 因此每次您變更的函式庫專案就要再安裝一次。而 npm link 是直接連結到該目錄不需要反覆安裝。

You might have more than one copy of React in the same app

接著,當我們繼續開發我們的 Hook 函式庫,在我們的專案中引用本地的函式庫專案就遭遇這個問題。解決的方式是在函式庫專案直接引用專案的 React

$ cd [YOUR_PACKAGE]
$ npm link [PROJECT]/node_modules/react

這個過程中您可能有和我一樣的疑問,如果部署到 npm 再安裝為什麼不會有參考的問題?那是因為您專案的 node_modules 裡函式庫並沒有自己的 node_modules 目錄,而 npm link 參考的本地卻有造成參考不一致。

資源

紀錄解決問題的過程中參考的資源:

--

--