Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hooks don't work with yarn link #14257

Closed
andy9775 opened this issue Nov 17, 2018 · 38 comments
Closed

Hooks don't work with yarn link #14257

andy9775 opened this issue Nov 17, 2018 · 38 comments

Comments

@andy9775
Copy link

andy9775 commented Nov 17, 2018

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
When developing an external library locally and using yarn link to link the library to a local react app the "hooks can only be called inside the body of a function component" error comes up. However, after publishing to npm and using the published version in the local react app everything works as expected.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:

  1. Create a library that's built with hooks (my-hooks-lib)
  2. Create a local app that uses the library (my-react-app) using CRA
  3. yarn link in my-hooks-lib and in my-react-app run yarn link my-hooks-lib

What is the expected behavior?
yarn start in the react app should use hooks and render normally

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
react and react-dom 16.7.0-alpha.2
OSX

@gaearon
Copy link
Collaborator

gaearon commented Nov 19, 2018

It's not expected that it would work unless you link react back from your module to your app.

This has actually always been the case (React apps are subtly broken when there are two copies of React module). Hooks surface this immediately which I guess is good.

We do have another issue tracking a better error message for this case.

@gaearon gaearon closed this as completed Nov 19, 2018
@andy9775
Copy link
Author

My mistake - first time using yarn link with react. Thanks for addressing @gaearon

@corysimmons
Copy link

corysimmons commented Jun 28, 2019

Is there a workaround for this? How can people locally test react components they want to turn into libraries? :\


Workaround is https://github.com/whitecolor/yalc

@dcecile
Copy link

dcecile commented Jul 5, 2019

If your React app is bundled with Webpack, you can use a Webpack alias to force all React references to resolve to a single module. In your webpack.config.js:

{
    /* ... */
    module: {
        rules: [ /* ... */ ],
    },
    resolve: {
        alias: { react: require.resolve("react") }
    },
}

(Solution from webpack/webpack#8607 (comment))

@maciekgrzybek
Copy link

@dcecile just to clarify, do you resolve that in the library you're working? or in the demo app?

@dcecile
Copy link

dcecile commented Jul 30, 2019

@maciekgrzybek I resolve it in the demo app

@maciekgrzybek
Copy link

Hey @dcecile thanks for a quick answer, sadly, that doesn't work for me as well.

@LucidityDesign
Copy link

I still get this error message even though I linked react and react-dom (via yarn link) and set react and react-dom as alias in my webpack.config:

'react': require.resolve('./node_modules/react'),
'react-dom': require.resolve('./node_modules/react-dom'),

@blkc
Copy link

blkc commented Feb 19, 2020

Currently there are like 3 ways you can install local dependencies,

  1. yarn link
  2. yarn add
  3. yarn add .tgz file

npm pack on the library repository and yarn add .tgz file in the other repo seems to work for me. The other two give me the hook error.

@jerrygreen
Copy link

jerrygreen commented Mar 5, 2020

Workaround:

cd PACKAGE_YOU_DEBUG_LOCALLY
yarn link
yarn install
cd node_modules/react
yarn link
cd ../../node_modules/react-dom
yarn link
cd YOUR_PROJECT
yarn link PACKAGE_YOU_DEBUG_LOCALLY
yarn link react
yarn link react-dom

I find it easier than some webpack setup or using yet another package manager (yapm? yanc? yalc? wut?)

@kas
Copy link

kas commented May 27, 2020

If you're having this issue when developing a package that exports a React component, and you have a folder structure like this:

react-component-package/
  package.json
web-application/
  package.json

Assuming react-component-package has React as a dev and peer dependency, you can run this command from the react-component-package folder:
npm link ../web-application/node_modules/react

The same command should work with Yarn:
yarn link ../web-application/node_modules/react

https://stackoverflow.com/a/58612244

@danantal
Copy link

danantal commented Jun 3, 2020

Will this be addressed somehow? I guess there is an workaround - but when you use create react app you can't really do any hacks in the webpack.config.js 😄

@aud
Copy link

aud commented May 4, 2021

@jaguardo in my experience Yalc removed a ton of the complexity that you would otherwise have to manage with symlinks yourself. Have been using it for a year or so now and the quality is very high. Worth giving it a shot for your use case.

@eric-burel
Copy link

For googlers, this issue can also be encountered for project using Webpack 4 and transitionning to Webpack 5. If I sum it up, yalc link does the reverse of yarn link regarding node_modules, favouring those of the project that rely on the package to avoid duplicates? By the way Meteor works this way when using METEOR_PACKAGE_DIRS, which has always been extremely more intuitive than link.
If yes that would solve the issue more elegantly.

@regalstreak
Copy link

Nothing worked but yalc for me

@L0rdH4x0r
Copy link

L0rdH4x0r commented May 11, 2021

Nothing from the above was needed! I got mine fixed by just keeping react and react-dom only as peerDependencies in package.json and delete all other occurrences. After that delete node_modules and package-lock.json and install again. Then in should work.

@eric-burel
Copy link

eric-burel commented May 11, 2021

Nothing from the above was needed! I got mine fixed by just keeping react and react-dom only as peerDependencies in package.json and delete all other occurrences. After that delete node_modules and package-lock.json and install again. Then in should work.

Most often, you cannot do this during development though, as you may need React for unit testing or 3rd party tools like Storybook. In a mono-repo, even if React is a peer-dependency of your package, it will fetch the "closest" version, so from your monorepo main node_modules instead of those from the app.
I've tested Yalc, with some success at the moment, though I am still not sure of the precise differences with a "normal" npm install.
This is how we intend to solve this for good in the future, taking inspiration from Meteor solution for this issue, based on an NPM_PACKAGE_DIRS environment variable: VulcanJS/vulcan-next#104

@austinrivas
Copy link

austinrivas commented May 11, 2021

yalc is the only solution to this problem (and the myriad of other issues caused by yarn/npm link) that consistently works.

Its pretty troubling that both yarn and npm seem convinced that naively symlinking entire directories ever worked.

@Omrilu-ma
Copy link

Those who still struggling with the issue and work with react-scripts without eject do the following to solve the issue:

  1. yarn add @craco/craco
  2. Change the package.json start script

From:

   "start": "react-scripts start",

To

   "start": "craco start",
  1. Add craco.config.js file to your root application with the following content:
const path = require('path')

module.exports = {
    webpack: {
        alias: {
            react: path.resolve(__dirname, './node_modules/react'),
            'react-dom': path.resolve(__dirname, './node_modules/react-dom'),
        },
    },
}

@alex-ds
Copy link

alex-ds commented Jul 2, 2021

In YOUR_PROJECT's package.json add into a jest config section:

...
  "jest": {
    "moduleNameMapper": {
        "^react$": "<rootDir>/node_modules/react",
        "^react-dom$": "<rootDir>/node_modules/react-dom"
    }
  }
...

It worked for me

@ramyNiranjan
Copy link

Workaround:

cd PACKAGE_YOU_DEBUG_LOCALLY
yarn link
yarn install
cd node_modules/react
yarn link
cd ../../node_modules/react-dom
yarn link
cd YOUR_PROJECT
yarn link PACKAGE_YOU_DEBUG_LOCALLY
yarn link react
yarn link react-dom

I find it easier than some webpack setup or using yet another package manager (yapm? yanc? yalc? wut?)

It works! Tks!

@ramyNiranjan
Copy link

This solution worked for me, Thanks a lot

@jquintozamora
Copy link

I configured this in webpack 5 and it's working for me:

module.exports = {
  //...
  resolve: {
    symlinks: false,
  },
}

@muratx10
Copy link

Workaround:

cd PACKAGE_YOU_DEBUG_LOCALLY
yarn link
yarn install
cd node_modules/react
yarn link
cd ../../node_modules/react-dom
yarn link
cd YOUR_PROJECT
yarn link PACKAGE_YOU_DEBUG_LOCALLY
yarn link react
yarn link react-dom

I find it easier than some webpack setup or using yet another package manager (yapm? yanc? yalc? wut?)

@jerrygreen thanks dude. You saved us. Works like a charm!

@zopelee
Copy link

zopelee commented Apr 14, 2022

Workaround:

cd PACKAGE_YOU_DEBUG_LOCALLY
yarn link
yarn install
cd node_modules/react
yarn link
cd ../../node_modules/react-dom
yarn link
cd YOUR_PROJECT
yarn link PACKAGE_YOU_DEBUG_LOCALLY
yarn link react
yarn link react-dom

I find it easier than some webpack setup or using yet another package manager (yapm? yanc? yalc? wut?)

@jerrygreen thanks dude. You saved us. Works like a charm!

Yes. Works like a charm, currently.

But someday, when you rm -rf node_modules or move the folder,

you will find, wow, something is screwed like a ****!

@DaviDevMod
Copy link

DaviDevMod commented Apr 20, 2022

Yes. Works like a charm, currently.

But someday, when you rm -rf node_modules or move the folder,

you will find, wow, something is screwed like a ****!

What about a postinstall script that creates the links? So that once you delete node_modules and run npm install you get the links back?

@DaviDevMod
Copy link

I had the same problem in a Next.js app and solved the issue with the approach suggested by dcecile. I added this entry in next.config.js:

webpack: (config) => {
  config.resolve.alias = {
    ...config.resolve.alias,
    react: path.resolve(__dirname, './node_modules/react'),
  };
  // Important: return the modified config
  return config;
},

Here are the docs for modifying Next.js webpack configuration.

@sickdyd
Copy link

sickdyd commented Jun 6, 2022

cd YOUR_PROJECT
cd node_modules/react
yarn link
cd ../react-dom
yarn link

cd PACKAGE_YOU_DEBUG_LOCALLY
yarn link
yarn install
yarn link react
yarn link react-dom

cd YOUR_PROJECT
yarn link PACKAGE_YOU_DEBUG_LOCALLY

I had problems using this workaround with React 18. The error was:

Module not found: Error: Can't resolve 'react-dom/client'

To make it work I had to downgrade to a previous React version.

Here the steps I followed:

  • go to package.json, and change the versions of both react and react-dom to:
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
  • change index.js to:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

  • yarn install (I also deleted the node_modules folder before this, but it should not be necessary)
  • then follow the steps of the original workaround

I hope this can help in case someone ends up having the same issue.

@jakebanks
Copy link

Yalc worked for me also, seems like a great tool

@valdemarrolfsen
Copy link

I created a small command line tool that solved this issue for me by watching the build folder of a project when developing locally and installing it in the node_modules of a destination project: https://github.com/valdemarrolfsen/herd.js.

Its a quite simple tool but it worked perfectly for me at least :)

@harpreetkhalsagtbit
Copy link

harpreetkhalsagtbit commented Apr 26, 2023

Currently there are like 3 ways you can install local dependencies,

  1. yarn link
  2. yarn add
  3. yarn add .tgz file

npm pack on the library repository and yarn add .tgz file in the other repo seems to work for me. The other two give me the hook error.

perfect.

yarn add .tgz file

Thanks @blkc

@Sassar88
Copy link

Those who still struggling with the issue and work with react-scripts without eject do the following to solve the issue:

  1. yarn add @craco/craco
  2. Change the package.json start script

From:

   "start": "react-scripts start",

To

   "start": "craco start",
  1. Add craco.config.js file to your root application with the following content:
const path = require('path')

module.exports = {
    webpack: {
        alias: {
            react: path.resolve(__dirname, './node_modules/react'),
            'react-dom': path.resolve(__dirname, './node_modules/react-dom'),
        },
    },
}

based on @Omrilu-ma solution, i got the following error, "craco Module not found: Error: You attempted to import /node_modules/react which falls outside of the project src/ directory."

I Solved this problem with the following additional configuration in Craco:

module.exports = {
  webpack: {
    alias: {
      react: path.resolve(__dirname, './node_modules/react'),
      'react-dom': path.resolve(__dirname, './node_modules/react-dom')
    },
    configure: (config, { env, paths }) => {

      const ModuleScopePlugin = config.resolve.plugins.find((plugin) => plugin instanceof ModuleScopePlugin);
      ModuleScopePlugin.allowedPaths.push(path.resolve(__dirname, './node_modules/react'));
      ModuleScopePlugin.allowedPaths.push(path.resolve(__dirname, './node_modules/react-dom'));

      return config;
    }
  },
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests