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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.podkrepi.bg/development/frontend/guidelines/react-guidelines.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
