Best Practices for Componentization and Code Reuse in ReactJS

Best Practices for Componentization and Code Reuse in ReactJS

Componentization is one of the most powerful features of ReactJS and the secret to building scalable, readable, and maintainable applications.

Componentizing is not just about breaking the code into small parts, but creating units that can be reused, understood in isolation, and easily tested. When thinking about components, we focus on modularity and reusability, two pillars that ensure productivity in development and significantly reduce code duplication.

Here are some best practices for componentization and reuse in ReactJS:

  • Small and Functional Components: Whenever possible, create components that have a clear responsibility and perform a single, well-defined task. This makes maintenance and reuse easier.
  • Avoid Side Effects: Don't put logic that interacts with external data (like making API calls) directly inside a reusable component. Instead, pass this logic as props to the component.

// Bad Practice: API call inside the component
const SaveButton = () => {
  return (
    <button onClick={() => doAPICall()}>Save</button>
  );
};

// Better Practice: Pass API call as prop
const SaveButton = ({ onClick }) => {
  return (
    <button onClick={onClick}>Save</button>
  );
};        

  • Props and Customization: Use props to make a component flexible. This way, the same component can be reused in different contexts by simply changing its properties.

// Button component
const Button = ({ color, label, onClick }) => {
  return (
    <button style={{ backgroundColor: color }} onClick={onClick}>
      {label}
    </button>
  );
};

// Using the Button component
<Button color="blue" label="Click Here" onClick={() => console.log("Button clicked!")} />        

  • Presentational vs. Container Components: Separate state logic from visual elements. Presentational components (or "dumb components") handle only the UI, while container components are responsible for handling state and business logic.

Example: A UserProfile component can be split into a presentational UserProfileView (which only handles the UI) and a container UserProfileContainer that manages data fetching and state.

// Presentational Component
const UserProfileView = ({ user }) => (
  <div>
    <h1>{user.name}</h1>
    <p>{user.bio}</p>
  </div>
);

// Container Component
const UserProfileContainer = () => {
  const [user, setUser] = React.useState(null);

  useEffect(() => {
    fetchUserData().then(setUser);
  }, []);

  return user ? <UserProfileView user={user} /> : <p>Loading...</p>;
};        

  • Custom Hooks: When you notice that you are replicating the same logic across multiple components, it's a good sign that a custom Hook can be created. This allows you to reuse logic in a cleaner and more organized way.

Example: If multiple components need to manage a timer, you can create a custom hook like useTimer that encapsulates the timer logic and makes it reusable.

// Custom Hook
const useTimer = (initialValue = 0) => {
  const [time, setTime] = useState(initialValue);

  useEffect(() => {
    const timer = setInterval(() => {
      setTime((prevTime) => prevTime + 1);
    }, 1000);

    return () => clearInterval(timer);
  }, []);

  return time;
};

// Using the Custom Hook
const TimerComponent = () => {
  const time = useTimer();
  return <div>Timer: {time} seconds</div>;
};        

  • Storybook for Components: Using a tool like Storybook helps document and test components in isolation, making reuse easier and improving communication among team members.

Example: By creating stories for each component, you can see how a Card component behaves with different props, ensuring it is tested in multiple scenarios and ready for reuse.

// Storybook example for Button component
export const PrimaryButton = () => (
  <Button color="blue" label="Primary" onClick={() => alert('Primary button clicked')} />
);        

Examples of Reusable React Components

  • Buttons: Basic buttons with different styles and functionalities.

import React from "react";

const Button = ({ color, label, onClick }) => {
  return (
    <button
      className={`padding-2 shadow-none hover:shadow background-light-${color} hover:background-dark-${color}`}
      onClick={onClick}
    >
      {label}
    </button>
  );
};

export default Button;

// Using the Button component
<Button color="blue" label="Click Here" onClick={() => console.log("Button clicked!")} />        

  • Navbars: Navigation bars that provide consistent navigation across your website.

import React from "react";

const Navbar = ({ isLoggedIn }) => {
  return (
    <div className="navbar">
      <div className="navbar-container">
        <div className="navbar-logo">
          <img src={logo} alt="logo" />
        </div>
        <div className="navbar-links">
          <a href="/">Home</a>
          <a href="/about">About</a>
          <a href="/contact">Contact</a>
          {isLoggedIn ? (
            <a href="/profile">Profile</a>
          ) : (
            <a href="/login">Login</a>
          )}
        </div>
      </div>
    </div>
  );
};

export default Navbar;

// Using the Navbar component
<Navbar isLoggedIn={true} />        

Well-done componentization results in cleaner code, reduces manual work, and facilitates long-term maintenance. When all developers on the team can reuse parts of the code instead of rewriting it, project efficiency skyrockets.

Conclusion

Congratulations! You've successfully learned how to build reusable React components.

Reusable components are the building blocks of robust React development. By practicing reusable components, you can build cleaner, more efficient, and more maintainable React applications.

The more you practice, the better you'll become at identifying opportunities to use them in your projects!

Illustration credit: Shahan

Read More: The Future of Frontend Development

Lucas Wolff

.NET Developer | C# | TDD | Angular | Azure | SQL

5 个月

Very informative

回复
Valmy Machado

Senior Frontend Engineer | Front-end Developer | React | Next | Svelte | Typescript | Node | Nest | AWS

5 个月

Amazing content

Karen Anhaia

Senior Software Engineer at Nubank | Clojure | Java | Spring | Microservices Architecture

5 个月

Very informative!

要查看或添加评论,请登录

José Roberto的更多文章

社区洞察

其他会员也浏览了