I have recently extracted some base react code from one of my projects into a separated shared project:
react-project package.json:
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1"
},
"devDependencies": {
"@types/node": "^16.11.45",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"@types/react-router-dom": "^5.3.3",
"react-app-alias-ex": "^2.1.0",
"react-app-rewired": "^2.2.1",
"typescript": "^4.7.4"
},
react-shared package.json:
"dependencies": {
"dotenv": "^16.0.1",
"graphql": "^16.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.3.0",
"redux-thunk": "^2.4.1",
"typesafe-actions": "^5.1.0"
},
"devDependencies": {
"@types/node": "^18.0.6",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"@types/react-router-dom": "^5.3.3",
"tailwindcss": "^3.0.22",
"tsconfig-paths": "^4.0.0",
"typescript": "^4.7.4"
}
And inside this shared project I have 2 Outlet implementations:
react-shared private.outlet.tsx:
export default class PrivateOutlet extends Component {
public constructor(props: any) {
super(props);
}
public render(): RenderResult {
if (loggedIn) {
return <Outlet />;
}
return <Navigate to="/login" replace />;
}
}
react-shared public.outlet.tsx:
export default class PublicOutlet extends Component {
public constructor(props: any) {
super(props);
}
public render(): RenderResult {
if (!loggedIn) {
return <Outlet />;
}
return <Navigate to="/" replace />;
}
}
The problem I'm having is that when I use those Outlets on the target project I get the error:
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: {...}
useOutlet hooks.tsx:214
Outlet components.tsx:110
{...}
But if I put those Outlets directly in the target project and remove the shared projects references to the Outlets, it works perfectly. Does anyone understand why this is happening and how I can fix it?
The problem was duplicate references due to me using a shared project and the react-app-alias-ex
package. I fixed it by adding the duplicate reference as an alias at config-overrides.js
:
const {aliasWebpack} = require('react-app-alias-ex');
const path = require('path');
const options = {
alias: {
'@my-shared': path.resolve('../PATH/TO/SHARED/src'),
'react-router-dom': path.resolve('./node_modules/react-router-dom')
}
};
module.exports = aliasWebpack(options);
There was another very weird problem that was causing this change to not work and I was able to make work by following these steps rigorously:
/node_modules
, /dist
and /package-lock.json
.npm install
.npm run react-app-rewired build
(If you are not using react-app-rewired
, running npm run react-scripts build
might work but I have not tested it).