Issue 1:
Do you want to request a feature or report a bug?

bug

What is the current behavior?

We are trying to create an external module which will be imported in main app.

Here is the module :

export const MyHelloComponent = (props) => {
const [test, setTest] = useState();
return (<div>Hello</div>);
}

Importing this simple code into main app gives us the error :

Uncaught Invariant Violation: Hooks can only be called inside the body of a function component

Removing hooks this code works fine.

We have followed instructions from https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react but error still thrown

If we link react as mentionned in documentation, works but it only can be done in development not in production.

We are not the only one having this issue Side package with React Hooks failing with Invariant Violation when called in main package

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:

Code from external component :

package.json

{
"name": "app-component",
"version": "1.0.0",
"main": "build/index.js",
"license": "MIT",
"private": true,
"peerDependencies": {
"react": "^16.8.4",
"react-dom": "^16.8.4"
},
"devDependencies": {
"@babel/core": "^7.3.4",
"@babel/plugin-proposal-class-properties": "^7.3.4",
"@babel/plugin-proposal-object-rest-spread": "^7.3.4",
"@babel/plugin-transform-react-jsx": "^7.3.0",
"@babel/plugin-transform-regenerator": "^7.3.4",
"@babel/preset-env": "^7.3.4",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.5",
"css-loader": "^2.1.0",
"react": "^16.8.4",
"react-dom": "^16.8.4",
"style-loader": "^0.23.1",
"styled-jsx": "^3.2.1",
"webpack": "^4.29.5",
"webpack-cli": "^3.2.3"
},
"scripts": {
"build": "./node_modules/.bin/webpack --mode production",
"dev": "./node_modules/.bin/webpack --mode development --watch"
},
"files": [
"build"
],
"dependencies": {
"@material-ui/core": "^3.9.2"
}
}

webpack.config.js

const path = require('path');
const pkg = require('./package.json');

const libraryName= pkg.name;

module.exports = (env, argv) => ({
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'index.js',
library: libraryName,
libraryTarget: 'commonjs2',
publicPath: '/build/',
},
devtool: argv.mode !== 'production' ? 'inline-source-map': false,
module: {
rules: [
{
test: /\.js$/,
include: path.resolve(__dirname, 'src'),
exclude: /(node_modules|bower_components)/,
use: ['babel-loader']
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
]
},

resolve: {
alias: {
'react': path.resolve('./node_modules/react'),
'react-dom': path.resolve('./node_modules/react-dom'),
}
},
externals: {
react: "react",
"react-dom": "react-dom"
}
});

src/index.js

export * from './components/hello';

src/components/hello.js

import React, { useState } from 'react';
export const MyHelloComponent = (props) => {
const [test, setTest] = useState();
return (<div>Hello</div>);
}

Code from main app:

webpack.config.js

module.exports = {
entry: './src/index.js',
output: {
path: __dirname + '/dist',
publicPath: '/dist/',
filename: 'bundle.js'
},
devServer: {
contentBase: './public',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
}
]
},
};

package.json

{
"name": "react-app-shell",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --mode development"
},
"dependencies": {
"react": "^16.8.4",
"react-dom": "^16.8.4"
},
"devDependencies": {
"@babel/core": "^7.3.4",
"@babel/preset-env": "^7.3.4",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.5",
"webpack": "^4.29.6",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.2.1"
}
}

src/index.js

import React from "react";
import ReactDOM from "react-dom";
import {MyHelloComponent} from 'app-component';

class Welcome extends React.Component {
render() {
return <><h1>Main App</h1><MyHelloComponent/></>;
}
}
ReactDOM.render(<Welcome />, document.getElementById("root"));

To be able to make it works, you have to do yarn link after (or before) having built it from component and yarn link "app-component" from main app.

What is the expected behavior?

use hooks from external components works obviously.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

React 16.8.4 and with previous version it doest not work too

Issue 2:
I want to save a class instance, not just plain object, with useRef hook. And, I dont want to construct it each time hook function is invoked.

Is it possible to do that?

My thoughts were:

const instanceRef = useRef(() => new Instance())

But useRef does not accept the initial value as a function (useState and useReducer could do that).

Will that change in alpha 3?