> For the complete documentation index, see [llms.txt](https://docs.podkrepi.bg/development/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.podkrepi.bg/development/frontend/guidelines/react-guidelines.md).

# 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.

```jsx
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`

```jsx
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`.

```typescript
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

#### Preferred export style :sun\_with\_face:&#x20;

* Nice IDE support and readability

{% tabs %}
{% tab title="RegisterPage.tsx" %}

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

{% endtab %}
{% endtabs %}

#### Alternative export styles

* Named function

  :partly\_sunny: Allows attaching static props to the function

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

  Register.getInitialProps = async (ctx) => {
    return { stars: 128 }
  }

  export default RegisterPage
  ```
* Const arrow function

  :sun\_with\_face: Nice for locally defined components

  ```
  const RegisterForm = () => <form>page</form>

  export default function RegisterPage() {
    return <RegisterForm />
  }
  ```

  :partly\_sunny: Okay for default exports, but not preferred

  ```
  const RegisterPage = () => <form>page</form>

  export default RegisterPage
  ```
* Unnamed arrow function :thunder\_cloud\_rain:&#x20;

  **Discouraged**

  <https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md>

  ```
  export default () => <div>page</div>
  ```
* Class components :thunder\_cloud\_rain:&#x20;

  **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](https://material-ui.com/components/box/)

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

:sun\_with\_face: Nice for quick layouts that should follow the theme

```jsx
<Box component="nav" px={5} mt={2}>
  <a>{t('nav.forgottenPassword')}</p>
</Box>
```

:partly\_sunny:*Not the best for custom scenarios with more than \_six* props passed to it. **Use `hooks` instead**

:partly\_sunny: *Not nice when the children have clear nesting structure of more than \_three* levels. **Use `hooks` or `scss` instead**

```jsx
<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

:sun\_with\_face: Nice for very specific styling that leverages `theme` methods and props

```jsx
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>
  )
}
```

:partly\_sunny: Too verbose for simple use cases, if it contains less than 2 css rules. **Use `Box` instead**

:partly\_sunny: Not the best when dealing with styling of deep nested structures within the same component. **Use `scss` instead**

#### Styles using SCSS files

Next.js supports [SCSS](https://sass-lang.com/) 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`)

:sun\_with\_face: Nice when dealing with complex nested structures that are scoped in a single component. When dealing with sub-components we're not sure if some of the rules will be left unused.

```css
@import 'styles/variables';

.page {
  color: $text-color;

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

    a {
      text-decoration: none;
      text-transform: uppercase;
    }
  }
}
```

```jsx
import styles from './about.module.scss'

<Box className={styles.page}>
  <p>{t('nav.forgottenPassword')}</p>
</Box>
```

:partly\_sunny: Too verbose for simple use cases, if it contains less than 2 css rules in a dedicated file. **Use `Box` instead**

```css
@import 'styles/variables';

a {
  text-decoration: none;
}
```

:thunder\_cloud\_rain: Cannot use theme support or theme variables **Use `hook` instead**
