React Guidelines

Imports

A common way to sort the imports in the file is by their source: external, absolute, relative separated by an empty line. Each of those groups can be sorted by line length, but that's not super important.

import React, { useState } from 'react'
import { useTranslation } from 'next-i18next'

import Nav from 'components/layout/Nav'
import Layout from 'components/layout/Layout'

import SimpleForm from './SimpleForm'
import styles from './advanced.module.scss'

File structure

Inherits AirBnb naming convention https://github.com/airbnb/javascript/tree/master/react#naming

Use PascalCase for React components and camelCase for their instances

Naming convention react components

Pascal cased file names src/components/GenericForm.tsx

export default function GenericForm() {}

Filename and default component of the file should have the same name.

Naming convention non react components

Camel cased file names src/utils/hooks/useUser.ts

Naming convention folders

Lowercase kebab cased folders src/components/common/password-reset/ResetForm.tsx

Naming convention pages

Lowercase kebab cased files located in src/pages/sample-page.tsx which correspond to /sample-page url.

Types

The common convention is that the main type of the component's props is called after the component itself with suffix -Props. Prop types of AdvancedForm becomes AdvancedFormProps.

type AdvancedFormProps = React.PropsWithChildren({
  title?: string
  age?: number
})

export default function AdvancedForm({ title = 'Nice', children, age }: AdvancedFormProps) {
  return (
    <div title={title} data-age={age}>
      {children}
    </div>
  )
}

Components

  • Nice IDE support and readability

export default function RegisterPage() {
  return <div>page</div>
}

Alternative export styles

  • Named function

    function RegisterPage() {
      return <div>page</div>
    }
    
    Register.getInitialProps = async (ctx) => {
      return { stars: 128 }
    }
    
    export default RegisterPage
  • Const arrow function

    const RegisterForm = () => <form>page</form>
    
    export default function RegisterPage() {
      return <RegisterForm />
    }
    const RegisterPage = () => <form>page</form>
    
    export default RegisterPage
  • Discouraged as hooks cannot be used inside the class components

    class Page extends React.Component {
      render() {
        return <div>page</div>
      }
    }

Styles

There are three common ways to style a component:

Styles using the <Box /> component

Single component that inherits all sizing props from MUI https://material-ui.com/system/basics/#all-inclusive

<Box component="nav" px={5} mt={2}>
  <a>{t('nav.forgottenPassword')}</p>
</Box>
<Box component="nav" px={5} pb={12} mt={2} mb={4} lineHeight={2} letterSpacing={none} fontSize={20}>
  <Box component="span" px={5} pb={12} mt={2} mb={4} lineHeight={2} letterSpacing={none} fontSize={17}>
    <a>{t('nav.forgottenPassword')}</p>
  </Box>
  <Box component="span" px={5} pb={12} mt={2} mb={4} lineHeight={2} letterSpacing={none} fontSize={13}>
    <a>{t('nav.forgottenPassword')}</p>
  </Box>
</Box>

Styles using useStyles() hook

const useStyles = makeStyles((theme) =>
  createStyles({
    pageTitle: {
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'center',
      padding: theme.spacing(4),
      margin: theme.spacing(5, 3, 4),
      color: theme.palette.secondary.main,
      backgroundColor: theme.palette.primary.main,
      '&:hover': {
        color: theme.palette.secondary.dark,
      },
    },
    // ...
  }),
)

export default function SomeBox() {
  const classes = useStyles()
  return (
    <Box className={classes.pageTitle}>
      <p>{t('nav.forgottenPassword')}</p>
    </Box>
  )
}

Styles using SCSS files

Next.js supports SCSS out of the box. Read more at https://nextjs.org/docs/basic-features/built-in-css-support#sass-support

File convention is based on a suffix .module.scss (ex. about.module.scss)

@import 'styles/variables';

.page {
  color: $text-color;

  .nav {
    background-color: $nav-color;

    a {
      text-decoration: none;
      text-transform: uppercase;
    }
  }
}
import styles from './about.module.scss'

<Box className={styles.page}>
  <p>{t('nav.forgottenPassword')}</p>
</Box>
@import 'styles/variables';

a {
  text-decoration: none;
}

Last updated