Developer Cheatsheets
Patterns Worth Knowing
Structuring Your Components

Sculpting Elegant Functional Components: An Art for Speedy React Development

Creating and maintaining a consistent structure for your functional components can exponentially improve code readability and maintainability. For advanced senior React developers aiming for speed and efficiency, here's a 4-pass approach to structuring React components with meticulous precision:

  1. Import Statements: Begin by incorporating necessary modules, libraries, or components required by the component. Always position these at the file's top for enhanced visibility and organization.
  2. Type Definitions: Here, you define types utilized within the component, such as prop types. Clearly defined types augment readability and ensure type safety, making debugging easier and more efficient.
  3. State Definitions: Define state variables utilized within the component using useState. These are fundamental to the component's behavior and may be used in the following sections.
  4. Side Effects: Implement side effects using useEffect that trigger when certain dependencies alter. They usually depend on the state and execute after render, meaning these should come after your state definitions.
  5. Functions/Handlers: Include functions or handlers related to component behavior, like event handlers. These could encompass complex logic affecting or depending on state and side effects.
  6. Return Statement: Lastly, the JSX that the component renders. Always at the end, logically following the setup and behavior, this is the component's output.

This sequence, from top to bottom, guarantees a logical flow in your component, transitioning from setup to output, thereby enhancing readability and simplifying maintenance.

Pass One: Laying the Foundation

Kick off by importing necessary modules, laying out your component, its props, and fundamental states.

// Import statements
import React, { useState } from "react";
 
interface MyComponentProps {
  initialCount: number;
}
 
const MyComponent: React.FC<MyComponentProps> = ({ initialCount }) => {
  const [count, setCount] = useState(initialCount);
 
  // Component logic goes here
 
  return <div>{/* Component rendering goes here */}</div>;
};
 
export default MyComponent;

Pass Two: Integrating Side Effects

Integrate useEffect for side effects connected to state or props modifications. Position useEffect after the declaration of state or any other variable it relies upon.

import React, { useState, useEffect } from "react";
 
interface MyComponentProps {
  initialCount: number;
}
 
const MyComponent: React.FC<MyComponentProps> = ({ initialCount }) => {
  const [count, setCount] = useState(initialCount);
 
  useEffect(() => {
    // Side effect based on count value changes
    console.log(`Count changed to: ${count}`);
  }, [count]);
 
  return <div>{/* Component rendering goes here */}</div>;
};
 
export default MyComponent;

Pass Three: Event Handlers and Auxiliary Functions

Introduce event handlers and helper functions. Define these preceding the return statement, after states and useEffects.

import React, { useState, useEffect } from "react";
 
interface MyComponentProps {
  initialCount: number;
}
 
const MyComponent: React.FC<MyComponentProps> = ({ initialCount }) => {
  const [count, setCount] = useState(initialCount);
 
  useEffect(() => {
    console.log(`Count changed to: ${count}`);
  }, [count]);
 
  const incrementCount = () => setCount(count + 1);
 
  return (
    <div>
      <button onClick={incrementCount}>Increment count</button>
    </div>
  );
};
 
export default MyComponent;

Pass Four: Leveling Up with Custom Hooks and Context

For components possessing intricate state logic or needing to disseminate state logic across multiple components, consider leveling up your code by refactoring it to use custom hooks or context.

// customHooks/useCount.ts
import { useState, useEffect } from "react";
 
const useCount = (initialCount: number) => {
  const [count, setCount] = useState(initialCount);
 
  useEffect(() => {
    console.log(`Count changed to: ${count}`);
  }, [count]);
 
  const incrementCount = () => setCount(count + 1);
 
  return { count, incrementCount };
};
 
export default useCount;
 
// components/MyComponent.tsx
import React from "react";
import useCount from "../customHooks/useCount";
 
interface MyComponentProps {
  initialCount: number;
}
 
const MyComponent: React.FC<MyComponentProps> = ({ initialCount }) => {
  const { count, incrementCount } = useCount(initialCount);
 
  return (
    <div>
      <button onClick={incrementCount}>Increment count</button>
    </div>
  );
};
 
export default MyComponent;

In this final step, the state logic has been relocated to a custom hook useCount, facilitating its reuse across different components. Notably, the consistent order is adhered to: import statements, type definitions, state definitions, side effect logic, event handlers and auxiliary functions, culminating in the component return statement. This structure provides a logical flow to the component, thus boosting readability and promoting efficient maintenance.

This approach of employing custom hooks promotes code reusability, while reducing complexity and redundancy, making your React application more maintainable and efficient. This pattern is a vital addition to any advanced React developer's toolkit as they race against time to deliver high-performing applications.