Modular Next.js Folder Strategy

Intro

Organizing your structure folder in Next.js is key to maintain a scalable and maintenable project, today i am gonna share one of the approach i use with Next.js page router.

βš™οΈ Part 0 – Next.js Configuration

This article us…


This content originally appeared on DEV Community and was authored by Daniel Dallimore Mallaby

Intro

Organizing your structure folder in Next.js is key to maintain a scalable and maintenable project, today i am gonna share one of the approach i use with Next.js page router.

βš™οΈ Part 0 - Next.js Configuration

This article use a custom folder that require you to change Next.js configuration, modify this line in the next.config.mjs file

const nextConfig = {
    pageExtensions: ["page.tsx"],
    ...
}

πŸ”„ Part 1 - Reusable vs Dedicated Components

The first thing we want to do is divide our project between generic Reusable component and dedicated components.
A reusable component is a component that can be used anywhere (for example the ReloadButton.tsx) while a dedicated component is a component that is relative so a specific page (for example the AboutMeHeader.tsx or the AboutMeBody.tsx)

β”œβ”€β”€ components/
β”‚   └── ReloadButton/
β”‚       └── ReloadButton.tsx
└── pages/
    └── about-me/
        β”œβ”€β”€ components/
        β”‚   β”œβ”€β”€ AboutMeHeader/
        β”‚   β”‚   └── AboutMeHeader.tsx
        β”‚   └── AboutMeBody/
        β”‚       └── AboutMeBody.tsx
        └── index.png

🧩 Part 2 - Component Structure Breakdown

For a better structure we want to divide a component into 5 parts: main, logic, style, configuration and types.

Let's see an example for a button that handle async requests

ReloadButton/
    β”œβ”€β”€ ReloadButton.tsx
    β”œβ”€β”€ ReloadButton.style.tsx
    β”œβ”€β”€ ReloadButton.conf.tsx
    β”œβ”€β”€ ReloadButton.d.tsx
    └── useReloadButton.tsx

Main - ReloadButton.tsx

This main component serve as a connector for all the other components.

import React from "react";
import { Button } from "./ReloadButton.style";
import useReloadButton from "./useReloadButton";
import { ReloadButtonProps } from "./ReloadButton.d";
import { buttonConfig } from "./ReloadButton.conf.tsx";

const ReloadButton = ({ message, onClick }: ReloadButtonProps) => {
  const { isReloading, handleReload } = useReloadButton({ onClick });

  return (
    <Button onClick={handleReload} disabled={isReloading}>
      {isReloading ? buttonConfig.loadingText : message}
    </Button>
  );
};

Style - ReloadButton.style.tsx

The style component isolate the style of this component, it can contains the style of child components in order to isolate all the style of a single component in one single file.
We can expose some variable to ReloadButton.conf in order for them to be more easy to be configurated

import styled from "styled-components";
import { buttonConfig } from "./ReloadButton.conf";

export const Button = styled.button`
  padding: 10px 20px;
  background-color: ${buttonConfig.backgroundColor};
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-size: 16px;

  &:hover {
    background-color: ${buttonConfig.hoverColor};
  }
`;

Logic - useReloadButton.tsx

This logic component contain all the states and function of the ReloadButton

While it's possible for the useReloadButton to contain also the logic of child component it's important to note that if u have a useState inside your useReloadButton there will be two different state (one for each component with the useReloadButton), consider solutions with Context or Redux for sharing customHooks between components.

import { useState } from "react";
import { UseReloadButtonProps } from "./ReloadButton.d";

const useReloadButton = ({ onClick }: UseReloadButtonProps) => {
  const [isReloading, setIsReloading] = useState(false);

  const handleReload = async () => {
    setIsReloading(true);
    await onClick();
    setIsReloading(false);
  };

  return {
    isReloading,
    handleReload,
  };
};

export default useReloadButton;

Type - ReloadButton.d.tsx

Type is used to store all the types of the component

export interface ReloadButtonProps {
  message: string;
  onClick: () => Promise<void>;
}

export interface UseReloadButtonProps {
  onClick: () => Promise<void>;
}

Config - ReloadButton.conf.tsx

Config is used to store all the constants and static configurations of the component

export const buttonConfig = {
  loadingText: "Reloading...",
  backgroundColor: "#0070f3",
  hoverColor: "#005bb5",
};

πŸ’‘ Part 3 - Example of usage

import React from "react";
import ReloadButton from "@/components/ReloadButton";

const App = () => {
  const handleReloadClick = async () => {
    await new Promise((resolve) => setTimeout(resolve, 2000));
    console.log("API call completed");
  };

  return (
    <div>
      <h1>Example App</h1>
      <ReloadButton message="Reload Data" onClick={handleReloadClick} />
    </div>
  );
};

export default App;

πŸ“Œ Part 4 - Conclusion

While this component could be considered overengineered, it's important to understand the structure in order to avoid having 2000 line files in bigger components!

One of the benefits of this solutions is improved search ,just search for your component name in vscode using CRTL + P or search for something like .style to search for all the styles around your application.

Thank you for reading this ,this was my first article and i hope you enjoyed :D


This content originally appeared on DEV Community and was authored by Daniel Dallimore Mallaby


Print Share Comment Cite Upload Translate Updates
APA

Daniel Dallimore Mallaby | Sciencx (2024-06-23T00:10:18+00:00) Modular Next.js Folder Strategy. Retrieved from https://www.scien.cx/2024/06/23/modular-next-js-folder-strategy/

MLA
" » Modular Next.js Folder Strategy." Daniel Dallimore Mallaby | Sciencx - Sunday June 23, 2024, https://www.scien.cx/2024/06/23/modular-next-js-folder-strategy/
HARVARD
Daniel Dallimore Mallaby | Sciencx Sunday June 23, 2024 » Modular Next.js Folder Strategy., viewed ,<https://www.scien.cx/2024/06/23/modular-next-js-folder-strategy/>
VANCOUVER
Daniel Dallimore Mallaby | Sciencx - » Modular Next.js Folder Strategy. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/06/23/modular-next-js-folder-strategy/
CHICAGO
" » Modular Next.js Folder Strategy." Daniel Dallimore Mallaby | Sciencx - Accessed . https://www.scien.cx/2024/06/23/modular-next-js-folder-strategy/
IEEE
" » Modular Next.js Folder Strategy." Daniel Dallimore Mallaby | Sciencx [Online]. Available: https://www.scien.cx/2024/06/23/modular-next-js-folder-strategy/. [Accessed: ]
rf:citation
» Modular Next.js Folder Strategy | Daniel Dallimore Mallaby | Sciencx | https://www.scien.cx/2024/06/23/modular-next-js-folder-strategy/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.