Jss: createUseStyles has access to theme without useTheme being passed

Created on 1 Oct 2020  路  14Comments  路  Source: cssinjs/jss

__Expected behavior:__
I had expected that not passing useTheme() to the useStyles() created by createUseStyles() would prevent the theme being available within createUseStyles

__Describe the bug:__
I can access the theme without passing anything to useStyles(). I couldn't find anything in the documentation that suggested this was intentional, so was hoping to clarify:

  • Is this an undocumented feature (in which case this pattern is safe to use)?
  • Is this a bug (in which case I should avoid the pattern)?
import { createUseStyles } from "react-jss";

const useStyles = createUseStyles((theme) => ({
  root: {
    border: "5px blue solid",
    borderColor: theme.themeColor // This correctly makes by border `themeColor`
  }
}));

export default function MyComponent({ text, customWidth }) {
  const classes = useStyles();

  return <div className={classes.root}>{text}</div>;
}

__Codesandbox link:__
https://codesandbox.io/s/createusestyles-automagic-theme-detection-8wks4?file=/pages/day/index.js

__Versions (please complete the following information):__

  • jss: (react-jss) 10.4.0
  • Browser [e.g. chrome, safari]: chrome
  • OS [e.g. Windows, macOS]: macOS
    Feel free to add any additional versions which you may think are relevant to the bug.

Most helpful comment

I think we could have <ThemeProvider theme={theme} useTheme={true}/> to turn on auto subscription to the theme

All 14 comments

I have noticed this as well, and initially thought this was intentional because of how props are handled in React.

If this is not intentional can someone please comment on here to confirm?

Honestly I think we should deprecate this interface entirely, because it it's hard to optimize and it creates yet another way to access the theme, where we have already other two - rule function and value function, it saves a few lines of code, but

  1. more syntaxes is more stuff to learn
  2. it's impossible to optimize in the sense that this function returns all new references and if any rule inside of them doesn't use a theme, it still will be treated as a new rule if theme changes

If not deprecating it, it would be more consistent if it wouldn't subscribe to the theme automatically but require user to pass it.

@kof Is there a way of correctly creating a function that will return the useStyles hook that can includes the theme?

I asked this on Gitter but I figure it might be in scope here:
I'm trying to avoid having to write this out in all of my styles component:

const useStyles = createUseStyles((theme: ThemeType) => ({...styles});
const theme = useTheme();
const classes = useStyles(theme);

I'm trying to create a new function which I would just call and not have to supply the theme directly.

const useThemedStyles = createThemedStyles({...styles});
// this would hopefully have access to the the theme without using the useTheme hook inside my component
// and without needing to pass in the theme explicitly in every file
const classes = useThemedStyles();

Is it worth optimizing 1 line of useTheme() and abstracting it away? Do you use the theme all over the place or mostly in the design system components and then only rarely?

I am finally setting up a proper theme to use globally throughout our web application, rather than just having an enum of Colors, and an object of different font styles.
I have a DashboardHeader, in that file I define my createUseStyles and pass it a theme prop with type, in the component I useTheme() and useStyles(theme).

We're currently hiring more developers and I'm trying to create a easy to follow style system. Having to call useTheme() and useStyles() along with passing in the theme in every createUseStyles() is just cumbersome.
It's not awful, just a nice qol improvement for the devs on my team if I could wrap all of that in a single call.

Do you have a design system components library?

Partially, not everything is using our current design language as we're rolling out a design rework at the moment.
This is from the DashboardHeader I was referencing earlier, in my createUseStyles:

  imageContainer: {
    gridArea: '1 / 1 / 3 / 2',
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'flex-start',
  },
  userIcon: {
    height: '80px !important',
    width: '80px !important',
    marginBottom: 8,
    cursor: 'pointer',
  },
  userType: {
    fontWeight: '400 !important',
    fontSize: 14,
    lineHeight: '16px',
    color: theme.colors.white,
  },

A lot of that is one off styling that wouldn't come from a component library. (font styling is being moved to the global theme shortly).

I think we could have <ThemeProvider theme={theme} useTheme={true}/> to turn on auto subscription to the theme

I think we could have <ThemeProvider theme={theme} useTheme={true}/> to turn on auto subscription to the theme

I like that idea, allows for less verbose usage of a provided theme if desired. But you could default that to false if people want more specificity in their code etc.

ps. Thanks for the quick responses!

Issue for adding this as a "feature": https://github.com/cssinjs/jss/issues/1418

The reason for passing it when needed was mostly perf based, but there are for sure cases where you want to override a theme or extend it from there. That interface can still allow it.

In any case, please create a separate issue, this discussion didn't belong here.

To sum up:

  • [x] Fix the docs to reflect the current behavior
  • [ ] Schedule removing of that createUseStyles(Function) interface for the major version upgrade

Fixed the docs. Closing this issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

janhartmann picture janhartmann  路  5Comments

sergiop picture sergiop  路  5Comments

HenriBeck picture HenriBeck  路  4Comments

pofigizm picture pofigizm  路  5Comments

EugeneSnihovsky picture EugeneSnihovsky  路  4Comments