1

I have to create the styles based on a param, for that i have done as below.

 const useStyles = (isLayoutReadOnly = false) =>
  makeStyles((theme: Theme) => {
    return {
      x: {
        margin: theme.spacing(0, 0, 1, 0),
          marginLeft: !isLayoutReadOnly ? '-20px' : undefined 
        }
      }
    };
  });

And i am trying to use it this way,

 const { x } = useStyles(isLayoutReadOnly);

Which throws me the error

property x does not exist on type '(props?: any) => ClassNameMap<"x">'

How should i fix this issue? I have tried setting the custom return types and also ReturnType<typeof makeStyles>, how ever, it is unable to detect.

Sin
  • 1,836
  • 2
  • 17
  • 24
  • What does your `makeStyles` function look like? – Andrew Hulterstrom Apr 20 '22 at 14:51
  • That is from materialUI /** * `makeStyles` where the passed `styles` do not depend on props */ `export default function makeStyles( style: Styles, options?: Omit, 'withTheme'> ): (props?: any) => ClassNameMap;` – Sin Apr 20 '22 at 14:58

1 Answers1

1

You are setting useStyles to a function that calls makeStyles:

const useStyles = (isLayoutReadOnly = false) => makeStyles()...

The example in the docs shows useStyles being set to makeStyles directly rather than to a function:

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      backgroundColor: theme.palette.red,
    },
  }),
);

You can achieve the same pattern with your code by using an Immediately Invoked Function Expression. By wrapping your function in (() => {}) parenthesis and then adding () parenthesis at the end, you can call your function immediately to make sure useStyles gets the return value of your (isLayoutReadOnly) => ... function. Here's how that would look:

  const useStyles = ((isLayoutReadOnly = false) =>
  makeStyles((theme) => {
    return {
      x: {
        margin: theme.spacing(0, 0, 1, 0),
          marginLeft: !isLayoutReadOnly ? '-20px' : undefined 
        }
      }
  }))(isLayoutReadOnly);

The other option is to adjust how you are calling useStyles. You can add an additional set of parenthesis to your call to useStyles to call the function that is returned to get the expected behavior:

  const  {x}  = useStyles(isLayoutReadOnly)();
Andrew Hulterstrom
  • 1,563
  • 4
  • 18
  • This answer helped me. The approach one is not working because, the function executed result is kept in `useStyles` and hence, further calls doesnt call the function with param to get the actual result. Second approach works, but it should be `const {x} = useStyles(isLayoutReadOnly)()` – Sin Apr 21 '22 at 04:10
  • Could you please edit the answer accordingly and i will accept it as answer. – Sin Apr 21 '22 at 04:11
  • Sure, just updated it. Does that look right? – Andrew Hulterstrom Apr 21 '22 at 04:13