DEV Community

Mayuresh Surve
Mayuresh Surve

Posted on

πŸš€ Day 6: Pure Component and UI as a Tree πŸš€

On Day 6 of my React learning journey, I explored two key concepts from the React documentation: Keeping Components Pure and Understanding Your UI as a Tree. These concepts are fundamental in writing efficient, maintainable, and scalable React applications. Let's dive into what I learned.


1. Keeping Components Pure

What Are Pure Components?

In React, a pure component is a component that returns the same output for the same set of inputs. It does not attempt to change or rely on anything outside its scope, making it predictable and easy to manage. This behavior is similar to pure functions in functional programming, where the function does not cause any side effects and does not alter its input data.

Principles of Pure Components

  • No Side Effects: Pure components avoid operations like modifying the DOM or global variables, making them easier to debug.
  • Consistency: Given the same props, a pure component will always render the same output, ensuring consistency across renders.
  • Ease of Testing: Because pure components are deterministic, they are easier to test and reason about.

Example

Consider a TemperatureConverter component that takes temperature in Celsius and converts it to Fahrenheit:

function TemperatureConverter({ celsius }) {
    const toFahrenheit = (celsius) => (celsius * 9) / 5 + 32;
    const fahrenheit = toFahrenheit(celsius);

    return (
        <p>
            {celsius}Β°C is {fahrenheit.toFixed(1)}Β°F
        </p>
    );
}

function App() {
    return (
        <div>
            <TemperatureConverter celsius={0} />
            <TemperatureConverter celsius={100} />
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Pure Function: toFahrenheit is a pure function used within the TemperatureConverter to ensure that the conversion is consistent and predictable.
  • Static Output: The TemperatureConverter always outputs the same result for the same celsius input, making it a pure component.

Impure Component Example

let clickCount = 0; // This global variable causes impurity

function ClickCounter() {
    // This side effect makes the component impure
    document.title = `Clicked ${clickCount} times`;

    return (
        <button onClick={() => clickCount++}>Clicked {clickCount} times</button>
    );
}
Enter fullscreen mode Exit fullscreen mode

Why Is This Component Impure?

  1. Global State Modification:
    The clickCount variable is defined outside the component. This makes it part of the global state, which can be accessed and modified by other components or functions, leading to unpredictable behavior.

  2. Side Effects:
    The component directly modifies the document.title each time it renders. This is a side effect because it changes the environment outside the component, which violates the principle of keeping components pure.

  3. Non-Deterministic Output:
    The component’s output changes based on the clickCount variable, which is not directly tied to its props or state. This makes the component's behavior unpredictable as it relies on external factors.

How to Make It Pure

To make this component pure, manage the state internally using React’s useState hook and avoid direct side effects in the component body:

import { useState, useEffect } from "react";

function ClickCounter() {
    const [count, setCount] = useState(0);

    useEffect(() => {
        document.title = `Clicked ${count} times`;
    }, [count]);

    return (
        <button onClick={() => setCount(count + 1)}>
            Clicked {count} times
        </button>
    );
}
Enter fullscreen mode Exit fullscreen mode

Improvements:

  • Local State Management:
    • Using useState ensures that the state (count) is encapsulated within the component, making it easier to manage and understand.
  • Controlled Side Effects:

    • The useEffect hook is used to handle side effects, such as updating the document.title. This hook only runs when the count changes, ensuring predictable behavior.
  • Deterministic Behavior:

    • The component’s output depends solely on its internal state, making it consistent and reliable across renders.

Benefits:

  • Optimized Rendering: React can optimize pure components by reducing unnecessary re-renders.
  • Better Performance: Pure components contribute to a faster and more efficient application.

For more details, explore the React documentation on keeping components pure.

2. Understanding Your UI as a Tree

Concept of UI as a Tree

React applications are built as component trees. Each React component is a node in this tree, forming a hierarchical structure. This tree model is crucial for React's rendering performance and helps manage complex UIs efficiently.

Key Aspects of UI as a Tree

  • Component Hierarchy: The UI is structured in a hierarchical tree where parent components can pass data to child components.
  • Efficient Updates: React updates the UI tree by only re-rendering components that have changed, thanks to its reconciliation algorithm.
  • Declarative Structure: The tree model allows developers to describe what the UI should look like for a particular state, and React handles the rest.

Example

Here's a simple app that displays a tree of categories and items:

function Category({ name, items }) {
    return (
        <div>
            <h3>{name}</h3>
            <ul>
                {items.map((item, index) => (
                    <li key={index}>{item}</li>
                ))}
            </ul>
        </div>
    );
}

function App() {
    const data = [
        { name: "Fruits", items: ["Apple", "Banana", "Orange"] },
        { name: "Vegetables", items: ["Carrot", "Broccoli", "Spinach"] },
    ];

    return (
        <div>
            <h1>Categories</h1>
            {data.map((category, index) => (
                <Category
                    key={index}
                    name={category.name}
                    items={category.items}
                />
            ))}
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Tree Structure: The App component is the root of the tree, with Category components as its children.
  • Dynamic Rendering: Each Category component dynamically renders a list of items, showcasing how React handles hierarchical data.

Benefits:

  • Clear Structure: The tree structure simplifies the UI design and makes it easy to visualize data flow.
  • Optimized Rendering: React efficiently updates the UI tree, minimizing unnecessary DOM updates.

For further insights, refer to the React documentation on understanding UI as a tree.

Conclusion

Grasping the concepts of pure components and UI as a tree is essential for developing efficient and robust React applications. Pure components help maintain consistency and optimize rendering, while understanding the UI as a tree aids in managing component hierarchies and efficient updates.

These principles not only improve the performance and scalability of your applications but also enhance the development experience by making the codebase more organized and maintainable.

For a deeper dive, check out the links provided for the official React documentation on these topics. Happy coding!

Feel free to connect with me on LinkedIn to stay updated on my latest projects and insights!

Top comments (0)