The Best and Most Different Way to Create Styles in React Apps using JSS and TypeScript

Create styles using JSS and TypeScript in react apps. With new and very interesting techniques

Omid Shah Hosseini
Webtips

--

The Best and Most Different Way to Create Styles in React Apps using JSS and TypeScript

You probably know and use a variety of ways to write styles in React apps, but today I want to show you a great new method that you may not have seen before.

What you will learn after reading this article:

  • Reason to use TypeScript instead of JavaScript
  • Reason to use JSS instead of other tools
  • Implement and create styles with JSS and TypeScript
  • Remove and separate the logic of styles from the logic of components
  • How can we have dynamic styles?

First, we will check some tools which you write styles in react applications:

  • CSS
  • CSS Preprocessors (Sass, Less, Stylus)
  • JSS
  • Styled Components
  • Styletron
  • Emotion
  • And more…

Why do we use JSS?
As you probably know, JSS is a JavaScript-based writing style that uses a set of features and extensions to make it a complete and powerful tool for writing styles. For example, we refer to Material UI, which is the most popular and undoubtedly the most complete and best UI framework for React, which uses JSS for its styles.
Also, by searching for the best performance benchmark, you will find that in many cases JSS performs better than other libraries.

Why do we use TypeScript?
If you have read about TypeScript you know that it has many features, these features allow us to have Type-Safe styles.
This is great because, with this feature and JSS features, we can avoid all the mistakes we may make in writing class names.
Another interesting feature of using TypeScript is the ability to write dynamic styles through Props, States, Variables, and anything else, all of which can be Type Safe.

JSS has some performance advantages:

  • Incremental compilation and rendering (as soon as needed).
  • Rendered styles are cached. Compilation and DOM Rules creation happens only once.
  • The only styles which are currently in use on your screen are also in the DOM (react-jss).
  • Simple class selectors ensure high selectors performance at scale.

Given that in this article we want to teach you how to create a style, we suggest that you visit the JSS website to read more features and details.

You can also create this style system using JavaScript, but you should know that in this case you will lose the TypeScript features.

Create and implement styles for components in React

Create and implement styles for components in React

To get acquainted with the features of writing style in this way, explanations are given step-by-step.

It is recommended that you write your styles outside of your React component to have more regular and readable styles, as well as better reusability.

Because our React project was created using TypeScript, we need to create React components with the .tsx extension and style files with the .ts extension.

Packages you need to install to create styles:
1- JSS:

command: npm install jss or yarn add jss
2- JSS Types:
command: npm install @types/jss or yarn add @types/jss
3- React JSS:
command: npm install react-jss or yarn add react-jss
4- React JSS Types:
command: npm install @types/react-jss or yarn add @types/react-jss

1- Create a React component

We want to create a button component, first in this step we create our button component with its props and the type of props.

Button.tsx

import React, { PropsWithChildren, ReactElement } from "react";type ButtonProps = {
color?: string;
bgColor?: "primary" | "secondary" | "transparent";
radius?: string;
size?: string;
};
function Button({
color = "",
bgColor = "primary",
radius = "0px",
size = "14px",
children,
}: PropsWithChildren<ButtonProps>): ReactElement {
return <button>{children}</button>;}export default Button;

2- Create a style for the component

At this stage, we have to implement our style.

Styles.ts

import { createUseStyles } from "react-jss";const getStyles = {
button: {
borderRadius: "0px",
color: "",
fontSize: "14px",
},
};
const useButtonStyles = createUseStyles(getStyles);export default useButtonStyles;

Note that useButtonStyles is a hook at this point.

So far we have only created one React component and its styles. Now in the next neighborhood, we have to use the styles in our React component.

3- Connecting styles to the react component

As you can see below, we should import useButtonStyles and create useStyle variable before returning.
Finally, we can access the desired styles with the useStyles command in the button.

Button.tsx

import React, { PropsWithChildren, ReactElement } from "react";
import useButtonStyles from "./styles";
type ButtonProps = {
color?: string;
bgColor?: "primary" | "secondary" | "transparent";
radius?: string;
size?: string;
};
function Button({
color = "",
bgColor = "primary",
radius = "0px",
size = "14px",
children,
}: PropsWithChildren<ButtonProps>): ReactElement {
const useStyles = useButtonStyles();return <button className={useStyles.button}>{children}</button>;}export default Button;
Type-Safe Styles in a Component

All right, after creating the component and style file and connecting and using it, we can make our styles Type-Safe.

But before that, we will mention the features of this work:

  • The possibility of error in using styles is reduced to zero.
  • Ability to implement the logic and dynamic styles, which we will get to it in the following.
  • When using useStyles to access class names after writing useStyles and pressing ctrl + space, the name of all created classes will be displayed to you and if you type incorrectly, the class name error will be displayed.

4- Type-Safe styles in a component

In this step, you must import Classes and Styles from the jss in the style file.

Styles.ts

import { createUseStyles } from "react-jss";
import { Classes, Styles } from "jss";

Then we create the following types and apply the specified changes to getStyles and useButtonStyles .

Also, from now on you have to type the class names in ButtonClassNames after creating it. For example, in the following section, we have created a class called secondClass.

import { createUseStyles } from "react-jss";export type ButtonClassNames = "button" | "secondClass";
export type ButtonClasses = Classes<ButtonClassNames>;
export type ButtonStyles = Styles<ButtonClassNames>;
const getStyles: ButtonStyles = {
button: {
borderRadius: "0px",
color: "",
fontSize: "14px",
},
secondClass: {},
};
const useButtonStyles: ButtonClasses = createUseStyles<ButtonClassNames>(
getStyles
);
export default useButtonStyles;

Now go back to our component and import the ButtonClasses that we created in our style file here and use it as follows:

Button.tsx

import React, { PropsWithChildren, ReactElement } from "react";
import useButtonStyles, { ButtonClasses } from "./styles";
type ButtonProps = {
color?: string;
bgColor?: "primary" | "secondary" | "transparent";
radius?: string;
size?: string;
};
function Button({
color = "",
bgColor = "primary",
radius = "0px",
size = "14px",
children,
}: PropsWithChildren<ButtonProps>): ReactElement {
const useStyles: ButtonClasses = useButtonStyles();return <button className={useStyles.button}>{children}</button>;}export default Button;

Great, now all your usable class names will be displayed after typing useStyles. The only difference is that you are absolutely sure of its existence.
But it’s not over yet, in the last step you will see how you can write dynamic styles and transfer the logic of your styles from the main component to the style file.

Dynamic style and transfer of their logic from the main component to the styles

In the following example, we want to check the display of a class name based on a prop. Usually, the following procedure is used to check a logical case for adding a class name.

Button.tsx

import React, { PropsWithChildren, ReactElement } from "react";
import useButtonStyles, { ButtonClasses } from "./styles";
type ButtonProps = {
color?: string;
bgColor?: "primary" | "secondary" | "transparent";
radius?: string;
size?: string;
};
function Button({
color = "",
bgColor = "primary",
radius = "0px",
size = "14px",
children,
}: PropsWithChildren<ButtonProps>): ReactElement {
const useStyles: ButtonClasses = useButtonStyles();return (
<button className={color === "" ? "white" : "black"}>
{children}
</button>
);
}export default Button;

Since checking the display of the class name on the button is related to the logic of adding or removing the class name in the main component, it is excellent to be able to separate this logic out of the main component and transfer it to the styles.

All we need for doing this is to remove our logic check from the button and give it a class name as before, and then send the props on useStyles Hook.

import React, { PropsWithChildren, ReactElement } from "react";
import useButtonStyles, { ButtonClasses } from "./styles";
type ButtonProps = {
color?: string;
bgColor?: "primary" | "secondary" | "transparent";
radius?: string;
size?: string;
};
function Button({
color = "",
bgColor = "primary",
radius = "0px",
size = "14px",
children,
}: PropsWithChildren<ButtonProps>): ReactElement {
const useStyles: ButtonClasses = useButtonStyles({color});return (
<button className={useStyles.button}>
{children}
</button>
);
}export default Button;

And inside the style file, receive the prop sent as shown below and use it for review.

Styles.ts

import { createUseStyles } from "react-jss";export type ButtonClassNames = "button" | "secondClass";
export type ButtonClasses = Classes<ButtonClassNames>;
export type ButtonStyles = Styles<ButtonClassNames>;
const getStyles: ButtonStyles = {button: ({ color = "" }) => ({
borderRadius: "0px",
color: color === "" ? "white" : "black",
fontSize: "14px",
}),
};
const useButtonStyles: ButtonClasses = createUseStyles<ButtonClassNames>(
getStyles
);
export default useButtonStyles;

But there is a problem yet! that types are type-safe only on component props.

But do not worry, we can do something interesting with another technique. Using the props component of the button and using them in the style file, we can also type-safe our style props.

To do this, first export the component props of the button:

Button.tsx

export type ButtonProps = {
color?: string;
bgColor?: "primary" | "secondary" | "transparent";
radius?: string;
size?: string;
};

Then import ButtonProps into your style file and then create a new type called ButtonStylesProps and set its value to ButtonProps.

Styles.ts

import { Classes, Styles } from "jss";
import { createUseStyles } from "react-jss";
import { ButtonProps } from "./Button";
export type ButtonClassNames = "button";
export type ButtonClasses = Classes<ButtonClassNames>;
export type ButtonStyles = Styles<ButtonClassNames>;
export type ButtonStylesProps = ButtonProps;
const getStyles: ButtonStyles = {
button: ({ color = "" }: ButtonStylesProps) => ({
borderRadius: "0px",
color: color === "" ? "white" : "black",
fontSize: "14px",
}),
};
const useButtonStyles: (
data?: ButtonStylesProps
) => ButtonClasses = createUseStyles<ButtonClassNames>(getStyles);
export default useButtonStyles;

Now not only the input values should be defined in the props of the button component also the types should be exactly correct.

You may ask if we want to change our styles based on states or variables, how should we do this? Because at the moment, styles only accept props as input.
All you have to do is make the following change when outputting

Styles.ts

// remove ButtonStylesProps and replace any
const useButtonStyles: (
data?: any
) => ButtonClasses = createUseStyles<ButtonClassNames>(getStyles);

Through this method, you can define a theme system for yourself and connect your theme to your styles and coordinate with it. If you want to learn it, be sure to leave your comments below this article.

Finally

Finally, you have created a new style system for your project that reduces the error rate to zero, and you can use this method to design all styles of your project.
As you have read, our class names are type-safe. We were also able to transfer the logic of our styles from the main component to the styles and have a dynamic component.
I hope you enjoy this new method and increase the level of style system improvement in your project.
Thank you.

--

--