I'm using lerna to create a monorepo where I'd have a structure like this:
root
packages
application - Our root application
components - Just some react components, that are to be used by the application
Here is a working Github with a simple example for this.
The issue I've run into, is I'm using Material-UI and its theming functionality, where at the application root we'll have a ThemeProvider:
import { ThemeProvider } from '@material-ui/styles';
//...
function App() {
return (
<ThemeProvider theme={theme}>
<MyMaterialComponent/>
</ThemeProvider>
);
}
And later in the library component, we consume the theme, in our case using the makeStyles
hook.
import React from 'react';
import { makeStyles } from '@material-ui/styles';
import Card from "@material-ui/core/Card";
const useStyles = makeStyles(theme => {
console.log(theme); //When this component doesn't have access to the theme, this is `{}`
return {
root: {
//color: theme.palette.primary.main //will error
}
}
});
export function MyMaterialComponent({ }) {
const classes = useStyles();
return (<Card>
<span className={classes.root}>This is some component</span>
</Card>
);
}
Now this seems all pretty straight forward. When we run this code all within the same package, it works fine. That styles function has access to the theme.
But when I'm running from another package (our application package), the the component library no longer has access to the theme (the theme is just an empty object).
The only way I currently know how to solve this, is the same way I've solved a similar hooks issue, which is to setup a webpack alias configuration in my application, to direct the component library to share the same same node module. (See this Github thread and the suggested solution).
ie. using react-app-rewired and customize-cra I have a config-overrides.js that looks like this:
const {
override,
addWebpackAlias,
} = require("customize-cra");
const path = require('path');
module.exports = override(
addWebpackAlias({
react: path.resolve('./node_modules/react'),
//comment out the line below to reproduce the issue
"@material-ui/styles": path.resolve("./node_modules/@material-ui/styles")
})
)
or you could be managing your webpack manually to do a similar thing.
So this works fine, but this isn't a particularly satisfying solution.
Especially for a library like Material-UI, you want users to be able to use your component library without having them to mess with their webpack configuration.
So I figure I must be doing something wrong here - can you tell me what?