Podkrepi.bg Development
DocsWebsiteGitHub
latest
latest
  • Introduction
  • Dev Guidelines
    • Branching strategy
    • Pull requests guidelines
    • Starting a task
    • Definition of done
    • Recognising Contributions
  • Architecture
  • Backend
  • Frontend
    • Guidelines
      • React Guidelines
      • Translations (i18n)
      • Forms
    • Environments
      • .env
      • Local Development
      • Production
  • Infrastructure
    • Deployment to Kubernetes
  • REST API
    • Authentication
    • Endpoints
      • Healthcheck
      • Contact Request
      • Support Request
      • Campaigns
  • GRAPHQL
    • Schema
Powered by GitBook
On this page
  • Imports
  • File structure
  • Types
  • Components
  • Styles

Was this helpful?

Export as PDF
  1. Frontend
  2. Guidelines

React Guidelines

PreviousGuidelinesNextTranslations (i18n)

Last updated 4 years ago

Was this helpful?

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

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

    export default () => <div>page</div>
  • 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:

<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

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;
}

Preferred export style

Allows attaching static props to the function

Nice for locally defined components

Okay for default exports, but not preferred

Unnamed arrow function

Class components

Styles using the

Single component that inherits all sizing props from MUI

Nice for quick layouts that should follow the theme

Not the best for custom scenarios with more than _six props passed to it. Use hooks instead

Not nice when the children have clear nesting structure of more than _three levels. Use hooks or scss instead

Nice for very specific styling that leverages theme methods and props

Too verbose for simple use cases, if it contains less than 2 css rules. Use Box instead

Not the best when dealing with styling of deep nested structures within the same component. Use scss instead

Next.js supports out of the box. Read more at

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.

Too verbose for simple use cases, if it contains less than 2 css rules in a dedicated file. Use Box instead

Cannot use theme support or theme variables Use hook instead

🌞
⛅
🌞
⛅
⛈️
⛈️
🌞
⛅
⛅
🌞
⛅
⛅
🌞
⛅
⛈️
https://github.com/airbnb/javascript/tree/master/react#naming
https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md
<Box /> component
https://material-ui.com/system/basics/#all-inclusive
SCSS
https://nextjs.org/docs/basic-features/built-in-css-support#sass-support