New component
Location and structure
The files and folder structure follows the
tightly-coupled architecture and
underlies the Next.js file-system router. That means that a file and code should live
as close as possible to its context. In the image below you can see we’ve a UserForm component that is located under
app/[locale]/(main)/users/add/_components. It does have other components it uses. Because they’re specific to it, they live in the
same folder (or subdirectories of the /_components folder) and follow the same architecture.

Details
General
- the component is located in:
- the 
_componentsfolder - a folder that is located inside the same directory as the component that uses it
 
 - the 
 - the file is named after the component and written in 
PascalCase 
Specific
- use functional components instead of class components
 
// ❌
class NewComponent extends PureComponent { ... }
 
// ✅
function NewComponent(...) { ... }Why?
- import types with 
import type { ... } from ...syntax 
// ❌
import { NewType } from ...
 
// ✅
import type { NewType } from ...- check size of imports (i.e. with VSCode plugin import costs) and reduce where possible (green is fine, red should be reviewed)
 
![]()
Why?
- use function declaration syntax instead of arrow function syntax.
 
// ❌
const NewComponent = (...) => { ... }
 
// ✅
function NewComponent(...) { ... }Why?
- export the functional component as default export (
export default MyComponent) and at the bottom of the file 
// ❌
export function NewComponent(...) { ... }
 
// ✅
function NewComponent(...) { ... }
...
export default function NewComponentWhy?
Next.js needs a React component to be exported via export default.
- type the component’s props with a TypeScript 
typeand destructure them where possible. 
// ❌
function NewComponent(cmpProps: { username: string; age: number; }) { ... }
 
// ❌
function NewComponent({ username, age }: { username: string; age: number; }) { ... }
 
// ✅
type Props = {
  username: string
  age: number
}
 
// NewComponent.tsx
function NewComponent({ username, age }: Props) { ... }Why?
- specify the return type of a component.
 
// ❌
function NewComponent(...) { ... }
 
// ✅
function NewComponent(...): JSX.Element { ... }Why?
By specifying the concret return type, TypeScript will give you an error if you accidentally return a wrong type. Additionally, it increases the consistency of always specifying the return type of functions throughout the codebase and provides a better readability if you can directly recognize what a function returns.
- declare types specific to a file inside the file at the top (like 
type Props) 
Why?
- logic that belongs together should live as close together as possible and they should be separated through a blank line.
 
// ❌
function NewComponent(...): JSX.Element {
  const [toggleColorTheme, setToggleColorTheme] = useState('light')
  const { t } = useTranslation()
  function onToggleColorTheme(): void {
    ...
    setToggleColorTheme('dark')
    ...
  }
}
 
// ✅
function NewComponent(...): JSX.Element {
  const { t } = useTranslation()
 
  const [toggleColorTheme, setToggleColorTheme] = useState('light')
 
  function onToggleColorTheme(): void {
    ...
    setToggleColorTheme('dark')
    ...
  }
}- Separate JSX elements with a blank line if they have the same indentation.
 
// ❌
function NewComponent(...): JSX.Element {
  return (
    <div>
      <div>
        <h2>Foo</h2>
      </div>
      <div>
        <h3>Bar</h3>
      </div>
    </div>
  )
}
 
// ✅
function NewComponent(...): JSX.Element {
  return (
    <div>
      <div>
        <h2>Foo</h2>
      </div>
 
      <div>
        <h3>Bar</h3>
      </div>
    </div>
  )
}- all texts are replaced with a corresponding 
i18nvariable 
// ❌
<h3>Login</h3>
 
// ✅
<h3>{t('login.title')}</h3>Why?
- avoid 
anywhere possible 
// ❌
function NewComponent(...): JSX.Element {
  const { t } = useTranslation()
 
  const [user, setUser] = useState<any>({ name: '', email: '' })
}
 
// ✅
type User = {
  name: string
  email: string
}
 
function NewComponent(...): JSX.Element {
  const { t } = useTranslation()
 
  const [user, setUser] = useState<User>({ name: '', email: '' })
}Why?
any you disable
TypeScript for it and don’t get any type-safety anymore. Some typing is hard, we
all know that, but at least ask for help and don’t go the simple and insecure way.- treat server requests as sensible
 
Why?
- provide feedback for every write, delete, update operation
 
Why?
- use proper code formatting via Prettier & linting via ESLint
 
Why?
- check console (browser and terminal) for any errors or warnings
 
Why?
Example
// NewComponent.tsx
import { User } from 'your-types-package'
 
type Props = {
  onSave: () => void
}
 
export function NewComponent({onSave}: Props): JSX.Element {
  const { t } = useTranslation()
 
  const [user, setUser] = useState<User>({ name: '', email: '' })
 
 
  const [toggleColorTheme, setToggleColorTheme] = useState('light')
 
  function onToggleColorTheme(): void {
    ...
    setToggleColorTheme('dark')
    ...
    onSave()
  }
 
    return (
    <div>
      <div>
        <h2>{t('newComponent.title')}</h2>
      </div>
 
      <div>
        <h3>{name}</h3>
      </div>
    </div>
  )
}