React Fundamentals

0% completed

Previous
Next
A Look at React's Best Practices

When learning React, it’s easy to focus on just making things “work”. However, understanding and applying best practices will help you write cleaner, more maintainable, and scalable code from the start.

In this section, we’ll explore best practices you can employ to help you build better React applications.

1. Use Functional Components Over Class Components

React initially relied on class components, but with the introduction of hooks, functional components are now the preferred way to write React applications. Functional components were used throughout this course because they are simpler, easier to understand, and more concise.

Why use Functional Components?

  • Cleaner Syntax: No need to manage this or lifecycle methods explicitly.
  • Hooks: Functional components can leverage hooks like useState and useEffect, which make handling state and side effects easier.
  • Performance: Functional components are lighter and work well with React's rendering optimizations.

Let's look at a counter application in a class component and how it is represented in a functional component.

class Counter extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } increment = () => { this.setState({ count: this.state.count + 1 }); }; render() { return ( <div> <p>Count: {this.state.count}</p> <button onClick={this.increment}>Increment</button> </div> ); } }

Here’s the same counter as a functional component:

import React, { useState } from "react"; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }

Looking at the functional representation of the counter component, you can see it is more cleaner, concise and involves less code.

2. Keep Components Small and Focused

In React, components should do one thing and do it well. Breaking your application into small, focused components makes the code easier to read, debug, and maintain.

Why use Small Components?

  • Reusability: Smaller components can be reused across the app.
  • Readability: Each component has a clear purpose, making the code more intuitive.
  • Testability: Testing isolated pieces of functionality becomes much easier.

Example

Let's look at a poorly structured component and how it can be split efficiently for easier management.

function App() { const [tasks, setTasks] = useState([]); const addTask = (task) => { setTasks([...tasks, task]); }; return ( <div> <h1>Task Manager</h1> <input type="text" placeholder="New Task" /> <button onClick={() => addTask("New Task")}>Add Task</button> <ul> {tasks.map((task, index) => ( <li key={index}>{task}</li> ))} </ul> </div> ); }

This component handles too many responsibilities. The best approach is to split it into smaller components:

function App() { const [tasks, setTasks] = useState([]); const addTask = (task) => { setTasks([...tasks, task]); }; return ( <div> <h1>Task Manager</h1> <TaskInput addTask={addTask} /> <TaskList tasks={tasks} /> </div> ); } function TaskInput({ addTask }) { return ( <div> <input type="text" placeholder="New Task" /> <button onClick={() => addTask("New Task")}>Add Task</button> </div> ); } function TaskList({ tasks }) { return ( <ul> {tasks.map((task, index) => ( <li key={index}>{task}</li> ))} </ul> ); }

In this example:

  • The responsibilites are split into two components namely: TaskInput and TaskList.
  • Each perform a specified task and are called in the App component with required props passed.

Think of your React components as a team. Instead of assigning all the work to one person (a giant component), delegate tasks to specialized team members (small components).

3. Leverage Reusable Components

Reusable components save time and effort by reducing duplication and making your app more consistent.

How to Create Reusable Components

  1. Identify repeated UI patterns or functionality.
  2. Extract the shared logic or structure into a single, reusable component.
  3. Use props to customize behavior or content.

Example

Let's look at a scenario whereby we need buttons in different places in our application. Instead of writing separate buttons, we can create one reusable button component and use wherever we want:

function Button({ onClick, label, color = "blue" }) { return ( <button style={{ backgroundColor: color }} onClick={onClick}> {label} </button> ); } // Usage function App() { return ( <div> <Button label="Save" onClick={() => alert("Saved!")} color="green" /> <Button label="Delete" onClick={() => alert("Deleted!")} color="red" /> </div> ); }

In this example:

  • The Button component recieves props (onClick, label and color set to a default of blue).
  • The App component renders the Button and passes the props.
  • style: Sets the button's background color using the color prop.
  • onClick: Executes the function passed through the onClick prop when clicked.
  • label: Displays the text passed through the label prop.

4. Comment on Code for Better Readability

As your application grows, your future self (and your teammates) will thank you for leaving helpful comments. Comments explain the "why" behind the code, especially when the logic is complex or not immediately clear.

Best Practices for Comments

  • Explain Intent: Describe why you’re doing something, not just what the code does.
  • Avoid Over-Commenting: Only comment on non-obvious parts of the code.
  • Update Comments: Ensure comments reflect the current state of the code.

Here, is an example of a good commenting style:

function fetchData() { // Fetching data from an external API fetch("https://api.example.com/data") .then((response) => response.json()) .then((data) => { // Process and set the fetched data setData(data); }) .catch((error) => { // Handle any errors during the fetch console.error("Error fetching data:", error); }); }

And this is a bad comment:

// Set the data setData(data); // This is obvious from the code itself!

5. Use React DevTools for Debugging and Performance

As web developers, we 'live' in the browser; you could say it's our playground. And as your React application expands, debugging and ensuring optimal performance can become challenging. This is where React Developer Tools (React DevTools) comes to the rescue. It is a browser extension that provides powerful tools for inspecting, debugging, and optimizing your React components.

Why Use React DevTools?

  • Inspect Component Hierarchies: View and navigate the structure of your React app.
  • Debug State and Props: Inspect the current state and props of any component in real-time.
  • Track Renders: Identify which components are re-rendering and why, helping you pinpoint performance bottlenecks.
  • Optimize Performance: Measure component re-renders and diagnose unnecessary re-renders using the Profiler tool.

How to Install and access React DevTools

  • Install the browser extension: There are extensions for Google Chrome, MicroSoft Edge and Firefox browsers.
  • Once installed, open the browser's developer tools (Ctrl+Shift+I or Cmd+Option+I), and you’ll see a React tab if you’re on a React application.

Using React DevTools

Let’s explore a few common scenarios where React DevTools can be helpful.

1. Inspecting Component Hierarchies

With React DevTools, you can visualize the tree structure of your components, making it easier to understand how they are nested and interact with each other.

For example, if your app renders incorrectly, you can inspect the hierarchy to confirm that the right components are being rendered where you expect them.

2. Debugging State and Props

React DevTools allows you to select any component and inspect its state and props.

Imagine a counter component where the count isn't updating. Using React DevTools, you can check if the state.count is changing correctly when the button is clicked. With DevTools, you can verify if count is being updated or if there’s an issue in the click handler.

3. Identifying Performance Bottlenecks

The Profiler tab in React DevTools helps you measure the rendering performance of your app.

A common use case is when your app feels sluggish, you can use the Profiler to check which components are re-rendering unnecessarily and optimize them.

Best Practices for Using React DevTools

  • Inspect State and Props Regularly: Avoid making assumptions about what your state or props should be—use DevTools to confirm.
  • Use the Profiler for Optimization: Track renders to identify inefficiencies and resolve them.
  • Test Component Updates: Validate changes in state and props when debugging interactive components like forms or counters.

Here is how the React DevTool (Component tab) looks like when running a React application:

Image

Think of React DevTools as a magnifying glass for your code. Instead of guessing why something is broken or slow, you can zoom in and see the details.

These practices may seem small, but they create a strong foundation for building scalable React applications.

Build and keep track of your application's structure and performance via React DevTools.

Happy coding! 🚀

.....

.....

.....

Like the course? Get enrolled and start learning!
Previous
Next