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
Preferred export style 🌞
Nice IDE support and readability
export default function RegisterPage() {
return <div>page</div>
}
Alternative export styles
Named function
⛅ 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
🌞 Nice for locally defined components
const RegisterForm = () => <form>page</form> export default function RegisterPage() { return <RegisterForm /> }
⛅ Okay for default exports, but not preferred
const RegisterPage = () => <form>page</form> export default RegisterPage
Unnamed arrow function ⛈️
Discouraged
https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md
export default () => <div>page</div>
Class components ⛈️
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
<Box />
componentSingle component that inherits all sizing props from MUI https://material-ui.com/system/basics/#all-inclusive
🌞 Nice for quick layouts that should follow the theme
<Box component="nav" px={5} mt={2}>
<a>{t('nav.forgottenPassword')}</p>
</Box>
⛅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
<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
useStyles()
hook🌞 Nice for very specific styling that leverages theme
methods and props
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>
)
}
⛅ 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
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
)
🌞 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.
@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>
⛅ Too verbose for simple use cases, if it contains less than 2 css rules in a dedicated file. Use Box
instead
@import 'styles/variables';
a {
text-decoration: none;
}
⛈️ Cannot use theme support or theme variables Use hook
instead
Last updated
Was this helpful?