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

makeStyles, withTheme and useTheme not working #14416

Closed
2 tasks done
ericsolberg opened this issue Feb 5, 2019 · 29 comments
Closed
2 tasks done

makeStyles, withTheme and useTheme not working #14416

ericsolberg opened this issue Feb 5, 2019 · 29 comments
Assignees
Labels
bug 🐛 Something doesn't work docs Improvements or additions to the documentation priority: important This change can make a difference
Milestone

Comments

@ericsolberg
Copy link

I'm trying to use the sample code for an app bar provided in the documentation (note that I'm not using the AppBar component- I have my own header component. But I'm currently trying to create a SearchField component based on this code). I've basically cut and pasted the code as-is, and pulled out the parts not related to the search field. I'm getting an error: Uncaught TypeError: Cannot read property 'borderRadius' of undefined. Digging into it, I see that the theme object being passed into the function I pass into makeStyles is an empty object. I investigated further, to see if I could get my hands on the theme. When I export my component with withTheme()(searchBar), the theme object in the props is null. Likewise, if I just call useTheme() in my component, it also returns null.

Note: it seems the plain JS sample code (no hooks) works - so this has something to do with the Material-UI and React 16.8.0-alpha.1. However- this version is required to use the sample hooks code.

  • This is not a v0.x issue.
  • I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior 🤔

My makeStyles function should be passed the populated theme object, and withTheme and useTheme should return the proper non-null theme object.

Current Behavior 😯

The theme object passed into makeStyles is empty. The theme props attribute injected by withTheme is null. The theme object returned by useTheme is null.

Steps to Reproduce 🕹

Link: I don't have a live link but it's easy to reproduce:

  1. create-react-app testy
  2. cd testy
  3. Modify package.json, setting the react and react-dom versions to ^16.8.0-alpha.1 (to make use of hooks)
    "react": "^16.8.0-alpha.1",
    "react-dom": "^16.8.0-alpha.1",
  1. npm install (to update react)
  2. npm install --save @material-ui/core @material-ui/styles @material-ui/icons
  3. Copy the Hooks version of the Sample App Bar with a primary search field
  4. Paste this code into the test app's /src/App.js file (overwrite the existing code) and save
  5. npm start - you will get an undefined error when the makeStyles function accesses the empty theme object

Context 🔦

I'm trying to implement a toolbar in my app with Material-UI.

Your Environment 🌎

Tech Version
Material-UI v3.9.2
React 16.8.0-alpha.1
Browser Chrome 71.0
TypeScript 3.3.0-rc
etc.
@eps1lon eps1lon added bug 🐛 Something doesn't work docs Improvements or additions to the documentation labels Feb 5, 2019
@eps1lon
Copy link
Member

eps1lon commented Feb 5, 2019

@ericsolberg This probably broke in #13229.

Be sure to follow https://material-ui.com/css-in-js/basics/#migration-for-material-ui-core-users in your own code.

@oliviertassinari
Copy link
Member

oliviertassinari commented Feb 5, 2019

@ericsolberg @material-ui/styles styling solution is standalone, it doesn't know anything about Material-UI components. You need to use the ThemeProvider from the style package with the const theme = createMuiTheme() function from the core package. You have an example here: https://github.com/mui-org/material-ui/tree/next/examples/nextjs-hooks.

This is exactly the type of frustration that working on v4 enable us to fix. I can think of the following possible approaches:

  • wrap the @material-ui/styles modules in @material-ui/core/styles to provide the default theme. Update the demos to reflect this change.
  • work on the DX by adding a warning. At least people will know, right from their console, the necessary steps.

@eps1lon I don't think that #13229 is linked.

@oliviertassinari oliviertassinari added the priority: important This change can make a difference label Feb 5, 2019
@oliviertassinari oliviertassinari added this to the v4 milestone Feb 5, 2019
@eps1lon
Copy link
Member

eps1lon commented Feb 5, 2019

@oliviertassinari It broke the dependencies in the codesandbox for hooks version. This shouldn't be an issue once stable react with hooks is released (which should've been yesterday).

@oliviertassinari
Copy link
Member

oliviertassinari commented Feb 5, 2019

Oh, so there are multiple problems :).

@krazyjakee
Copy link

wrap the @material-ui/styles modules in @material-ui/core/styles to provide the default theme.

would this mean const useStyles = makeStyles(theme => ({ would pass the global theme variable without a ThemeProvider? If so, great! I'm not happy to wrap hundreds of components with (yet another) provider just to access the theme.

@oliviertassinari oliviertassinari self-assigned this Feb 10, 2019
@caedmon
Copy link

caedmon commented Feb 13, 2019

@ericsolberg I'm new to both ts and mui so don't really know what I'm doing, but what worked for me was:

import { Theme } from '@material-ui/core/styles/createMuiTheme';
...
const theme = useTheme<Theme>();

(using createMuiTheme and Theme from @material-ui/core/styles and all else from @material-ui/styles)

@VincentLanglet
Copy link
Contributor

I have a similar issue and I'm not sure to understand what I did wrong.
The "red" primary color is not used anymore.

Before

import { createMuiTheme, MuiThemeProvider } from '@material-ui/core/styles';

const theme = createMuiTheme({
  palette: {
    primary: red,
  },
});

export default <MuiThemeProvider theme={theme}>
...
<MuiThemeProvider />

After

import { createMuiTheme } from '@material-ui/core/styles';
import { ThemeProvider } from '@material-ui/styles';

const theme = createMuiTheme({
  palette: {
    primary: red,
  },
});

export default <ThemeProvider theme={theme}>
...
<ThemeProvider />

Before

const NavBar = ({ classes }: WithStyle<ClassKey>): ReactElement => {
  return (
    <AppBar position="fixed" className={classes.appBar}>
      <Toolbar>
        <Typography color="inherit" variant="h6">
          App
        </Typography>
      </Toolbar>
    </AppBar>
  );
};

type ClassKey = 'appBar' | 'toolbar';

const styles = (theme: Theme): StyleRules<{}, ClassKey> => ({
    appBar: {
      zIndex: theme.zIndex.drawer + 1,
    },
    toolbar: theme.mixins.toolbar,
  }),
);

export default withStyles(styles)(NavBar)

After

const NavBar = (): ReactElement => {
  const classes = useStyles();

  return (
    <AppBar position="fixed" className={classes.appBar}>
      <Toolbar>
        <Typography color="inherit" variant="h6">
          App
        </Typography>
      </Toolbar>
    </AppBar>
  );
};

type ClassKey = 'appBar' | 'toolbar';

const useStyles = makeStyles(
  (theme: Theme): StyleRules<{}, ClassKey> => ({
    appBar: {
      zIndex: theme.zIndex.drawer + 1,
    },
    toolbar: theme.mixins.toolbar,
  }),
);

export default NavBar

@joshwooding
Copy link
Member

@auctus1989
Copy link

Hey folks, thanks for your work on this project. I am having the exact same issue. With ThemeProvider the theme doesn't seem to be applied. I am definitely doing the bootstrap step.

With MuiThemeProvider the theme is applied but the makeStyles function does not get the Theme object. makeStyles does get it with ThemeProvider.

@joshwooding
Copy link
Member

@mrstafford makeStyles is part of @material-ui/styles, therefore it is only intended to work with the ThemeProvider.

@auctus1989
Copy link

auctus1989 commented Mar 5, 2019

@joshwooding yep :). I was explaining my situation, I should have been more clear. I think the specific problem is with ThemeProvider not applying the theme whereas if I use MuiThemeProvider it works fine.

This is with the following dependencies:
"@material-ui/core": "^4.0.0-alpha.2",
"@material-ui/icons": "^4.0.0-alpha.1",
"@material-ui/styles": "^4.0.0-alpha.2",
"jss": "^10.0.0-alpha.12",

The code is pretty simple:

<StylesProvider jss={myJss} generateClassName={generateClassName}> 
    <ThemeProvider theme={myTheme}>
        <CssBaseline />
        <MyPage />
    </ThemeProvider>
</StylesProvider>

@joshwooding
Copy link
Member

@mrstafford Do you have a reproduction I can have a look at?

@auctus1989
Copy link

auctus1989 commented Mar 5, 2019

@joshwooding I believe the following codesandbox displays the issue. If you change ThemeProvider to MuiThemeProvider it will change the background color to dark.

https://codesandbox.io/s/q9lmro76y4?fontsize=14

Actually. Really strangely it was showing the issue when I created it. Now it is working. I'll try to see the difference between it and my project.

@joshwooding
Copy link
Member

@mrstafford When I view your codesandbox I get the dark background straight away (using the ThemeProvider)

@auctus1989
Copy link

auctus1989 commented Mar 5, 2019

@joshwooding you are right. When I remove, save and then re-add import "./bootstrap"; it breaks again.

@auctus1989
Copy link

@joshwooding figured it out. the import "./bootstrap"; must be the very top import of the index.js. i.e.

import "./bootstrap";
import React from "react";
import ReactDOM from "react-dom";
import App from "./app";

instead of

import React from "react";
import ReactDOM from "react-dom";
import App from "./app";
import "./bootstrap";

Thank you for your help.

@joshwooding
Copy link
Member

joshwooding commented Mar 5, 2019

@mrstafford Your bootstrap is being imported after your App, it should be before

Looks like you beat me to it :)

import React from "react";
import ReactDOM from "react-dom";
import "./bootstrap";
import App from "./app";

will work as well

@mrgab0
Copy link

mrgab0 commented Jul 2, 2019

it is a human error of appreciation

correct way

import { ThemeProvider } from '@material-ui/styles';
import { createMuiTheme } from '@material-ui/core/styles';

wrong way

dont use like this "import { ThemeProvider, createMuiTheme } from '@material-ui/core/styles';"

error is related to a typeof but sounds like a package error: Attempted import error: 'ThemeProvider' is not exported from '@material-ui/core/styles'.

@eps1lon
Copy link
Member

eps1lon commented Jul 3, 2019

dont use like this "import { ThemeProvider, createMuiTheme } from '@material-ui/core/styles';"

You can use imports "like this". Just import the correct names (ThemeProvider -> MuiThemeProvider).

@lookfirst
Copy link
Contributor

I just wasted a few hours on figuring out why my theme wasn't being applied... hopefully this comment helps someone:

This compiles and auto-completes in my IDE using typescript, but definitely does not work:

import ThemeProvider from "@material-ui/styles/ThemeProvider/ThemeProvider";

It should just be:

import {ThemeProvider} from "@material-ui/styles";

@oliviertassinari
Copy link
Member

@lookfirst What's your IDE? Do you have a way to configure it, to get the correct import?

@lookfirst
Copy link
Contributor

IDEA. Sure, you can pick the right import from the list, but I picked the wrong one because I've been badly trained in the past to pull the most 'complete' import so that tree shaking would work better. Yes, I know that is moot these days, but whatever... Would be nice if MUI had a more restricted set of exports so that stuff like this didn't get picked up by accident.

@oliviertassinari
Copy link
Member

@lookfirst I can't find any way to configure the auto-import from our side. Tree-shaking should work with the latest version of Material-UI. You should also be able to leverage https://material-ui.com/guides/minimizing-bundle-size/#option-2 for better perf in dev mode.

@lookfirst
Copy link
Contributor

@oliviertassinari

Control the exports. Google Firebase client (not admin) SDK has some crazy crazy stuff going on in that department if you want to look into it.

Since option 2 is the 'best UX/DX', shouldn't it be noted as option 1? =) Also, I'm using CRA, so updating the instructions to make sure that usecase is covered seems like a wise option given the ubiquity of that solution. That said, from what I can tell, it just magically works. But you're more of an expert than I on this matter... so best to double check.

@oliviertassinari
Copy link
Member

@lookfirst It does work, but its 10-30% slower to start your dev server. Yeah CRA is a challenge. It requires the usage of another dependency. I can't find any material on the auto import work Firebase has done. Do you have a link to share?

@lookfirst
Copy link
Contributor

@oliviertassinari
Ah, yea I've noticed starting up dev is pretty slow. I guess that must be it. Doh.

In the above link, you mention: "Pick one of the following plugins:" for the babel option two. Just some feedback, it would be nice to know the differences between those two options. Why should I pick one plugin over the other? The confusing morass of TS / JS / Babel / CRA / etc... makes it an endless rabbit hole and any little extra bit of information there helps a lot. Thanks!

Here is the info on firebase:

https://firebase.google.com/docs/web/setup
npm install --save firebase

Then try clicking through to see the tricks they employ with typescript/npm/package.json.

@oliviertassinari
Copy link
Member

It seems that they have inlined everything at the root: https://unpkg.com/browse/firebase@6.3.5/index.d.ts.

@lookfirst
Copy link
Contributor

@oliviertassinari Ah yes, but dig a little deeper:

https://unpkg.com/browse/firebase@6.3.5/app/package.json
https://unpkg.com/browse/firebase@6.3.5/app/dist/index.esm.js

They push all the 'code' into @firebase/app... this way you can't accidentally import from there.

@oliviertassinari
Copy link
Member

Thanks for the details. It's an interesting approach. We should consider having a flat file for each folder, maybe it's actually better than what we do now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work docs Improvements or additions to the documentation priority: important This change can make a difference
Projects
None yet
Development

No branches or pull requests

10 participants