React JSS and TypeScript
Asked Answered
C

1

6

I've been using React for a while, and now I want to switch to using React with TypeScript. However, I've grown used to JSS styles (via the react-jss package), and I can't understand how I'm supposed to use them with TypeScript. I also use the classnames package, to assign multiple class names conditionally, and I get TypeSCript errors for that.

Here is my React component template:

import React, { Component } from 'react';
import withStyles from 'react-jss';
import classNames from 'classnames';

const styles = theme => ({
});

class MyClass extends Component {
    render() {
        const { classes, className } = this.props;
        return (
            <div className={classNames({ [classes.root]: true, [className]: className})}>
            </div>
        );
    }
};

export default withStyles(styles)(MyClass);

I'm just learning TypeScript, so I'm not sure I even understand the errors I get. How would I write something like the above in TypeScript?

UPDATE

Here is how I finally converted my template:

import React from 'react';
import withStyles, { WithStylesProps }  from 'react-jss';
import classNames from 'classnames';

const styles = (theme: any) => ({
    root: {
    },
});

interface Props extends WithStylesProps<typeof styles> {
    className?: string,
}

interface State {
}

class Header extends React.Component<Props, State> {
    render() {
        const { classes, className } = this.props;
        return (
            <div className={classNames({ [classes.root as string]: true, [className as string]: className})}>
            </div>
        );
    }
};

export default withStyles(styles)(Header);

Things to keep in mind:

  • when defining the styles object, any member of classes that is referenced in the render method has to be defined. Without TypeScript, you could get away with "using" lots of classes and not defining them, like a placeholder; with TypeScript, they all have got to be there;
  • in a call to the classnames function, all the keys must be typed. If they come from a variable that could be null or undefined, you have to add as string, or to convert them to string otherwise. Other than this, the className property works the same as without TypeScript.
Cardoso answered 6/1, 2020 at 23:54 Comment(2)
Could you share an example of the errors you are getting?Hemline
@Hemline I don't think they are significative. I couldn't find any reference on React JSS with TypeScript, and tried to "fix" things as I stumbled into them. So most of the errors were probably caused by me trying wrong solutions.Cardoso
A
1

With TypeScript, you'll need to define your props as shown in here. It is also recommended to use function component if your React component only need render method

For your case, the code should look like this:

import React from 'react';
import withStyles, { WithStyles } from 'react-jss';
import classNames from 'classnames';

const styles = theme => ({
  root: {

  }
});

interface IMyClassProps extends WithStyles<typeof styles> {
  className: string;
}

const MyClass: React.FunctionComponent<IMyClassProps> = (props) => {

    const { classes, className } = props;
    return (
        <div className={classNames({ [classes.root]: true, [className]: className})}>
        </div>
    );
};

export default withStyles(styles)(MyClass);
Airt answered 7/1, 2020 at 0:15 Comment(4)
Thanks for the pointers! I'm getting this error on row 2, on "WithStyles": Module '"<app-path>/node_modules/react-jss/src"' has no exported member 'WithStyles'. Did you mean to use 'import WithStyles from "<app-path>/node_modules/react-jss/src"' instead?, which seems absurd to me...Cardoso
I've found that WithStyles is deprecated in favor of WithStyleProps. Is this what you meant? github.com/cssinjs/jss/blob/…Cardoso
Now I'm getting A computed property name must be of type 'string', 'number', 'symbol', or 'any' when I use my component without specifying a value for className. However, I don't always want to specify it - but if I change IMyClassProps's definition to include className?: string then I get the error above.Cardoso
One last update: I managed to make it compile (pass the type checks) by using ${className} in backticks. Thank you!Cardoso

© 2022 - 2024 — McMap. All rights reserved.