Best Practices

1. Keep Files Close to Their Usage

  • Organize files within the smallest relevant scope to maintain clarity and reduce complexity.

  • Avoid placing helper functions or components at the global scope unnecessarily.

  • Example: If a utility function is only used by CreateForm.jsx and EditForm.jsx, place it inside components/Form/utils.js instead of src/utils.js.

  • Global utilities should only be used if shared across multiple unrelated modules.


2. Semantic Naming with PascalCase

  • Name components and folders semantically using PascalCase.

  • Avoid vague or arbitrary names; names should reflect the purpose of the component.

  • Examples:

    // Bad
    const Right_Section = () => {};
    const snake_case_component = () => {};
    
    // Good
    const UserDetails = () => {};
    const UserProfileDetails = () => {};
    

3. Use index.ts / index.tsx in Component Folders

  • Use index files to consolidate exports within a folder, simplifying imports.

  • Example:

    // src/components/commons/index.js
    import Header from "./Header";
    import PageLoader from "./PageLoader";
    export { Header, PageLoader };
    
    • Then, in other files:

    import { Header, PageLoader } from "components/commons";
    

4. Export Conventions

  • Use default export for single components.

  • Use named exports only when exporting multiple entities from the same file.

  • Example:

    // Default export
    export default EmptyState;
    
    // Named exports
    export const Header = () => {};
    export const Footer = () => {};
    

  • Combine related state variables into a single object to reduce boilerplate.

  • Example:

    const [ticketDetails, setTicketDetails] = useState({
      title: "",
      description: "",
      count: null,
      assignee: null,
    });
    
  • Always use functional updates to avoid race conditions when updating multiple states asynchronously:

    setTicketDetails(prev => ({ ...prev, title: newTitle }));
    

6. Organize Hooks Properly

  • Keep all useState hooks at the top of the component.

  • Follow with other hooks (useEffect, useMemo, custom hooks) for readability.

  • Group hooks logically and separate them visually with new lines.

  • Exceptions are allowed if useState depends on a context or router value.


7. Destructure Props & API Responses

  • Destructure props in the component signature for cleaner code and better IDE support:

    // Bad
    const UserProfile = props => <h1>{props.name}</h1>;
    
    // Good
    const UserProfile = ({ name, title }) => <h1>{name}</h1>;
    
  • Destructure API responses to simplify state updates:

    const { ticket: { title, description } } = await api.getTickets();
    setTicketTitle(title);
    setTicketDescription(description);
    

8. Avoid Unnecessary <div> Wrappers

  • Return the component directly if no wrapper is needed:

    // Bad
    return <div><Button /></div>;
    
    // Good
    return <Button />;
    

9. Use Modern JSX & JavaScript Patterns

  • Template literals for dynamic strings:

    const userDetails = `${user.name} works at ${user.company}`;
    
  • Self-closing tags for components with no children:

    <Button label="Submit" />
    
  • Object literals for conditional rendering when ternaries or switch statements become messy:

    const components = { ADMIN: Admin, AGENT: Agent, CUSTOMER: Customer };
    const Component = components[role];
    return <Component />;
    

10. Place API Routes Correctly (Next.js)

  • Store backend route handlers inside the app/api folder following Next.js conventions:

    src/app/api/products.js
    src/app/api/orders.js
    

11. Additional Tips

  • Keep code DRY: Reduce duplication using reusable functions or components.

  • Minimal logic in JSX: Keep render code simple, move complex logic to helper functions.

  • Use boolean shorthand for props:

    <Button disabled /> // instead of disabled={true}
    
  • Semantic props naming: Use camelCase for props (e.g., phoneNumber, userName).

  • Spread operator for forwarding remaining props:

    const Button = ({ label, ...otherProps }) => <Child {...otherProps} />;