React ES6

ES6 transformed how we write JavaScript. No more verbose variable declarations with var let and const. Keep your code clean and prevent unintended scope issues. Template literals make string manipulation a breeze, allowing for embedded expressions and multi-line strings without awkward concatenation. Destructuring lets you unpack values from objects and arrays in a compact and readable way, saving you time and reducing the chance of errors. If you’re building modern web apps, especially with React, mastering ES6 is a must-have skill.

React-ES6
Table of Contents

React, and the Power of Modern JavaScript

React leverages modern JavaScript features (ES6 and beyond) to deliver a clean and expressive development experience. These features allow you to write concise and readable code, streamlining the process of building React components and applications. Here’s how some of these features come into play:

Functional Component with Arrow Function Example

import React from 'react';

const MyComponent = () => {
    return (
        <div>
            <h1>Hello, World!</h1>
        </div>
    );
};

export default MyComponent;

Explanation

  • Line 1: Imports React from the 'react' library.
  • Line 3: Defines a functional component named MyComponent using an arrow function. This is a concise way to define components in ES6 compared to traditional function declarations.
  • Lines 4-8: The component returns JSX code that defines the UI structure (a div containing an h1 element).
  • Line 11: Exports the MyComponent to be used in other parts of your application.

Key Points

  • Arrow Functions: Provide a shorter syntax for defining functions than traditional function declarations (no need for the function keyword or return statement if the function body is an expression).
  • JSX: Enables writing HTML-like syntax within JavaScript code to define the UI structure of your components.

Using modern JavaScript features, React empowers developers to write cleaner, more maintainable, and more expressive code, making the development process more efficient and enjoyable.


What is ES6?

ES6, also known as ECMAScript 2015, is a significant update to the JavaScript language released in 2015. It introduced many new features that make writing JavaScript code cleaner, more concise, and more powerful. These features are especially beneficial for building complex web applications, including those built with React.

Breakdown of ES6 along with its key significance for JavaScript development:

ES6: A Major JavaScript Transformation

  • Standardization: ES6 refers to the 6th edition of the ECMAScript language specification. ECMAScript is the standardized version of JavaScript.
  • Massive Update: This version introduced many new features, modernizing JavaScript and making it more powerful and expressive for developers.

Why ES6 is Important

  • Cleaner Code
    ES6 provided features that make code more concise, readable, and easier to maintain, including:
    • Arrow functions (=>)
    • Template literals (backticks ``)
    • let and const keywords for variable declaration
    • Destructuring
    • Spread syntax (...)
  • New Tools
    ES6 introduced crucial new functionalities that unlocked new development patterns and ways to handle data, such as:
    • Classes (for object-oriented programming)
    • Modules (for code organization and reusability)
    • Promises (for managing asynchronous operations)
    • Array methods like map and filter

Impact on React and Modern Web Development

  • Foundation for React: React heavily embraces ES6 features, making its components and patterns possible.
  • Broader Ecosystem: ES6 has become the baseline for modern web development. Tools, libraries, and most new JavaScript code utilize ES6 features.

Key Features to Know

ES6 and Beyond have revolutionized JavaScript development, offering features that simplify your coding life! From streamlined variable declarations with let and const to easier string manipulations with template literals, you’ll write cleaner, more expressive code. Destructuring and the spread operator make working with collections like objects and arrays a breeze. Mastering array methods like .map(), .filter(), and more allows you to transform data with concise functional approaches. Lastly, introducing modules ensures code modularity, reusability, and better project organization.

Arrow Functions in React ES6

Arrow functions (denoted by =>) are a powerful feature introduced in ES6 that provides a concise and readable way to define functions in JavaScript. React heavily utilizes arrow functions for various functionalities within components, making your code more expressive and easier to maintain.

Event Handler with Arrow Function Example

import React from 'react';

function Button() {
    const handleClick = () => {
        console.log('Button Clicked!');
    };

    return (
        <button onClick={handleClick}>Click Me</button>
    );
}

export default Button;

Explanation

  • Line 1: Imports React from the 'react' library.
  • Lines 3-11: Define a functional component named Button.
    • Lines 4-6: Define an arrow function named handleClick using the const keyword. This function logs a message to the console when clicked.
    • Line 9: JSX for the button element. The onClick event handler is assigned the handleClick function, ensuring the function is called when the button is clicked.

Arrow functions are particularly useful in React for defining event handlers within components or for callback functions. They offer a cleaner alternative to traditional function expressions, especially when the function body is short and straightforward.

Arrow Functions and the “this” Puzzle in React ES6

In React, understanding how this keyword behaves is crucial. Traditional function declarations have their own this binding, which can lead to confusion when dealing with event handlers within components. Arrow functions, however, offer a solution with their lexical this binding.

Lexical this vs. Traditional this

  • Lexical this
    Refers to this value from the function’s surrounding scope. Arrow functions inherit this from their enclosing context.
  • Traditional this
    Defined by how the function is called. In event handlers within React components, this might refer to the DOM element instead of the component itself.

Button with Traditional vs. Arrow Function Example

import React from 'react';

class TraditionalButton extends React.Component {
    handleClick() {
        console.log(this); // This refers to the component instance
    }

    render() {
        return (
            <button onClick={this.handleClick.bind(this)}>
                Click Me (Traditional)
            </button>
        );
    }
}

const ArrowButton = () => {
    const handleClick = () => {
        console.log('Arrow Function');
    };

    return (
        <button onClick={handleClick}>
            Click Me (Arrow)
        </button>
    );
}

export { TraditionalButton, ArrowButton };

Explanation

  • Line 3-15: Defines a class component named TraditionalButton which extends React.Component.
    • Line 4-5: Declares a traditional function handleClick that logs the component instance to the console.
    • Line 8-13: Implements the render method to output a button. The method .bind(this) is used on handleClick to ensure this within handleClick refers to the component instance.
  • Line 17-27: Defines a functional component ArrowButton using an arrow function.
    • Line 18-19: Inside ArrowButton, declares an arrow function handleClick that logs a string. Arrow functions do not have their this context, so this refers to the enclosing lexical context.
    • Line 22-25: Returns a button element where onClick is assigned to the handleClick arrow function.
  • Line 29: Exports both components to be imported and used in other files.

The behavior of this varies significantly between the traditional function approach used in the TraditionalButton class component and the arrow function used in the ArrowButton functional component. Here’s how:

Traditional Functions and this

  • In traditional functions, the value of this depends on how the function is called. This can lead to confusion and the need to explicitly bind this to the correct context.
  • In the TraditionalButton example, .bind(this) is necessary to make sure this inside handleClick refers to the component instance.

Arrow Functions and this

  • Arrow functions don’t have their own this. They inherit it from the place where they’re defined.
  • This makes them naturally suited for event handlers in React functional components, as you often don’t need to worry about manually binding this.

Arrow functions simplify how this works in React components. This often removes the need for explicit binding, making your code cleaner and less prone to errors.

Classes with Inheritance in React ES6

React allows you to define components using classes. Classes provide a structured way to manage component state, lifecycle methods, and logic. Inheritance in React enables you to create new components that inherit properties and behaviors from existing ones, promoting code reuse and reducing redundancy.

While functional components with Hooks are generally preferred, here’s a basic example of classes with inheritance

Button and PrimaryButton Example

import React from 'react';

class Button extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <button {...this.props}>
                {this.props.children}
            </button>
        );
    }
}

class PrimaryButton extends Button { // Inherits from Button
    constructor(props) {
        super(props);
        this.state = { isLoading: false }; // Add state specific to PrimaryButton
    }

    handleClick = () => {
        this.setState({ isLoading: true });
        // Simulate async operation
        setTimeout(() => this.setState({ isLoading: false }), 1000);
    };

    render() {
        const { isLoading } = this.state;
        return (
            <button {...this.props} onClick={this.handleClick} disabled={isLoading}>
                {isLoading ? 'Loading...' : this.props.children}
            </button>
        );
    }
}

export default PrimaryButton;

Explanation

  • Lines 3-15: Define a base class component Button.
    • Line 3: Extends React.Component.
    • Lines 8-14: The render method returns a button element, spreading props ({...this.props}) for flexibility.
  • Lines 17-37: Define a new component PrimaryButton inheriting from Button.
    • Line 17: Extends the Button class.
    • Lines 18-21: Adds a constructor with initial state (isLoading) specific to PrimaryButton.
    • Lines 23-27: Defines a handleClick function that simulates an asynchronous operation using state.
    • Lines 29-36: The render method overrides the inherited render method.
      • Lines 32-34: Uses conditional rendering based on isLoading state to display "Loading..." the button content.
  • Line 39: Exports the PrimaryButton component.

Key Points

  • Classes: Offer a structured approach to component creation with state management and lifecycle methods.
  • Inheritance: Enables code reuse by creating child components that inherit properties and behaviors from parent components.
  • State Management: Child components can introduce additional state specific to their functionality.
  • Consider Trade-offs: While classes with inheritance can be useful for complex components, functional components with Hooks are often preferred for their simplicity and alignment with modern React practices.

Variable Management with let and const in React (ES6)

React uses ES6 features like let and const for variable declarations. These keywords provide more control over variable scope and immutability than the traditional var keyword, leading to cleaner and more predictable code.

Understanding Scope

  • Block Scope: Variables declared with let and const are only accessible within the block they are defined (e.g., curly braces { }). This prevents accidental variable conflicts.

Using Let and Const Example

import React from 'react';

function Counter() {
    let count = 0; // Declare count using 'let'

    const increment = () => {
        count++; // Can modify 'count' because it's declared with 'let'
    };

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={increment}>Increment</button>
        </div>
    );
}

export default Counter;

Explanation

  • Line 4: Declares a variable count with let. This variable is only accessible within the Counter function (block scope).
  • Line 6: Declares a constant increment using const. Constants cannot be reassigned after their initial value.
  • Line 7: increment function modifies the count variable because it’s declared with let (mutable).
  • Lines 12: Display the current count value.
  • Line 13: Button click handler calls the increment function to increase the count.

Key Points

  • let: Use let for variables that need reassignment within their scope.
  • const: Use const for variables that hold fixed values and should not be changed. This promotes immutability and prevents accidental modifications.
  • Block Scope: Both let and const have block scope, which improves code clarity and reduces the risk of variable conflicts.

By effectively using let and const in React, you can write more predictable and maintainable code, ensuring variables are used as intended within their defined scope.

Dynamic Strings with Template Literals in React (ES6)

Template literals, introduced in ES6 and denoted by backticks (``), offer a powerful and readable way to create strings in JavaScript. They are particularly useful in React for constructing dynamic content within JSX.

Template Literals vs. Concatenation

  • Traditional string concatenation can be cumbersome for complex strings with variables.
  • Template literals allow for easier interpolation of variables and expressions directly within the string.

Greeting with Template Literal Example

import React from 'react';

function Greeting({ name }) {
    const message = `Hello, ${name}!`; // Template literal with variable interpolation

    return (
        <div>
            <h1>{message}</h1>
        </div>
    );
}

export default Greeting;

Explanation

  • Line 4: Defines a constant message using a template literal.
    • Backticks (``) enclose the string.
    • ${name} inserts the value of the name prop within the string.
  • Line 8: Displays the message variable within <h1> tag, rendering the dynamic greeting.

Key Points

  • Interpolation: Embed variables and expressions directly within the string using ${ } syntax.
  • Multiline Strings: Template literals allow multiline strings without concatenation or escape characters, improving readability.
  • Readability: Template literals enhance code clarity, especially when dealing with complex string formatting.

Using template literals in React, you can create dynamic and user-friendly content by seamlessly incorporating variables and expressions into your JSX.

Traversing and Transforming Arrays in React with ES6 Methods

React heavily relies on arrays to manage data lists and collections. ES6 provides powerful array methods like .map() and .filter() that simplify working with arrays within your components.

Understanding Array Methods

  • .map(): Creates a new array with the results of calling a function on every element in the original array.
  • .filter(): Creates a new array with elements that pass a test implemented by the provided function.

Product List with Filtering Example

import React, { useState } from 'react';

function ProductList() {
    const [products, setProducts] = useState([
        { id: 1, name: 'Product A', inStock: true },
        { id: 2, name: 'Product B', inStock: false },
        { id: 3, name: 'Product C', inStock: true },
    ]);

    const filterProducts = (inStock) => {
        return products.filter((product) => product.inStock === inStock);
    };

    return (
        <div>
            <h2>Products</h2>
            <button onClick={() => setProducts(filterProducts(true))}>In Stock</button>
            <button onClick={() => setProducts(filterProducts(false))}>Out of Stock</button>
            <ul>
                {products.map((product) => (
                    <li key={product.id}>{product.name}</li>
                ))}
            </ul>
        </div>
    );
}

export default ProductList;

Explanation

  • Line 1: Imports the React library and the useState hook, which manages the state within functional components.
  • Line 3: Defines a functional component named ProductList.
  • Line 4-8: Uses useState to initialize the products state with an array of product objects.
  • Line 10-11: Defines a function filterProducts that filters products based on their inStock status.
    • Line 11: Filters the products array to include only products that match the given inStock status.
  • Line 17-18: Adds two buttons to filter products by their stock status. When clicked, they set the products state to the result of filterProducts, thus updating the displayed list.
    • Line 17: Filters for products that are in stock.
    • Line 18: Filters for products that are out of stock.
  • Line 19-23: Displays the products as a list. Each product is rendered as a list item (<li>) within an unordered list (<ul>), using map to iterate over the products array.
    • Line 21: Renders the product’s name in a list item using the product’s id as a key.
  • Line 28: Exports the ProductList component.

Key Points

  • .map(): Ideal for transforming each item in an array into a new element for rendering (e.g., product list items).
  • .filter(): Useful for creating new arrays based on specific criteria, allowing you to display filtered content.
  • State Management: Filtering often involves updating component state to reflect the changes in the displayed data.

Unpacking Data with Destructuring in React (ES6)

Destructuring is a powerful ES6 feature that allows you to extract specific properties or values from objects and arrays in a concise and readable way. This can be particularly beneficial in React when dealing with component props and state objects.

Benefits of Destructuring

  • Improved Readability: Destructuring avoids repetitive prop or state object access, making code cleaner and easier to understand.
  • Flexibility: You can extract specific properties you need, ignoring unused ones.

Destructuring Props Example

import React from 'react';

function UserCard({ name, email, website }) { // Destructuring props
    return (
        <div>
            <h2>{name}</h2>  {/* Access props directly using destructured names */}
            <p>Email: {email}</p>
            <a href={website}>Website</a>
        </div>
    );
}

export default UserCard;

Explanation

  • Line 3: Define a functional component UserCard.
    • Destructuring is used directly in the function arguments to extract specific props (name, email, and website) from the incoming props object.
  • Lines 6-8: Access the destructured props directly by name within the JSX, improving readability.

Key Points

  • Destructuring Syntax: Use curly braces { } for objects and square brackets [ ] for arrays.
  • Extracting Properties: Assign destructured properties to variables with the desired names.
  • Ignoring Unused Props: You can omit unused props from the destructuring pattern.

Spread/Rest (...) Operator in React (ES6)

The spread operator (...) is a versatile ES6 feature that offers two functionalities in React: spreading elements and properties and collecting remaining elements into an array.

Understanding Spread Operator

  • Spreading Elements/Properties
    Used to unpack elements from arrays or properties from objects, allowing you to copy or modify existing structures.
  • Collecting Elements
    Gathers remaining elements into a new array, often used with destructuring to capture unwanted elements.

Spreading for Form Defaults Example

import React, { useState } from 'react';

function ContactForm() {
    const initialValues = { name: '', email: '', message: '', };

    const [formData, setFormData] = useState(initialValues);

    const handleChange = (event) => {
        setFormData({ ...formData, [event.target.name]: event.target.value });
    };

    return (
        <form onSubmit={(e) => e.preventDefault()}>
            <label>
                Name:
                <input type="text" name="name" value={formData.name} onChange={handleChange} />
            </label>
            <br />
            <label>
                Email:
                <input type="email" name="email" value={formData.email} onChange={handleChange} />
            </label>
            <br />
            <label>
                Message:
                <textarea name="message" value={formData.message} onChange={handleChange} />
            </label>
            <br />
            <button type="submit">Send Message</button>
        </form>
    );
}

export default ContactForm;

Explanation

  • Line 3: Declares a functional component named ContactForm.
  • Line 4: Defines the initial state for the form data with empty strings for nameemail, and message.
  • Line 6: Initializes the formData state with initialValues using the useState hook.
  • Line 8-9: handleChange function updates formData state when input changes. It uses the input’s name to identify the key to update and sets its value.
  • Line 13: The form uses onSubmit to prevent its default submit action, preventing the page from reloading upon submission.
  • Line 14-17: A label and text input for the user’s name. The value and change handler are bound to formData.name.
  • Line 19-21: A label and email input for the user’s email. The value and change handler are bound to formData.email.
  • Line 24-26: A label and textarea for the user’s message. The value and change handler are correctly bound to formData.message.
  • Line 29: A submit button for the form.

Modules (import/export) in React (ES6)

React uses ES6 modules for code organization. Modules allow you to export functionalities (functions, components) from one file and import them into other parts of your application, promoting reusability and modularity. There are two main types of exports: named exports and default exports.

Greeting Module and Component Example

Greeting.js (Module File)

import React from 'react';

export function greet(name) { // Named export using 'export' keyword
    return `Hello, ${name}!`;
}

const PI = 3.14159; // Not exported (for internal use)

export default function GreetingComponent({ name }) { // Default export
    return (
        <h1>{greet(name)}</h1> // Using the exported greet function
    );
}

App.js (Component File)

import GreetingComponent, { greet } from './Greeting.js'; // Import named and default exports

function App() {
    return (
        <div>
            <p>{greet('World')}</p>  {/* Using imported greet function */}
            <GreetingComponent name="Alice" />  {/* Using imported GreetingComponent */}
        </div>
    );
}

export default App;

Explanation (Greeting.js)

  • Lines 3-5: Define a function greet and export it using export. This makes it accessible to other modules.
  • Line 7: Constant PI is not exported, keeping it private within the module.
  • Lines 9-13: Define a React component GreetingComponent as the default export using export default. This component utilizes the previously exported greet function.

Explanation (App.js)

  • Line 1: Imports both the greet function and the GreetingComponent from Greeting.js.
    • Named imports use curly braces { } to specify which exports to import.
    • greet should be imported as a named export, and GreetingComponent is the default export.
  • Lines 3-10: Define the App component.
    • Line 6: Uses the imported greet function to display a greeting message.
    • Line 7: Uses the imported GreetingComponent and passes a prop (name) to it.

Key Points

  • Named Exports: Allow you to export multiple functionalities (functions, components) from a single module using descriptive names.
  • Default Export: A module can only have one default export, typically a single component or function.
  • Importing: You can import named exports using curly braces and specify which ones you need. The default export can be imported without curly braces.

You can create well-structured React applications with reusable components and functions using exports and imports.


Using ES6+ Features in React Components

ES6+ features significantly streamline your React development process! let and const give you precise control over variable scope, keeping your components organized. Template literals make string creation and embedding variables a breeze, resulting in cleaner presentation code. Array methods like .map() and .filter() let you manipulate and display data dynamically, adding a layer of responsiveness to your UI. Destructuring and spread operators tidy up how you work with props and state. Overall, embracing ES6+ features leads to more readable, efficient, and maintainable React components.

Classes vs. Functional Components in React

React offers two primary approaches to creating components: classes and functional components. Here’s a quick comparison and guidance on choosing the right approach:

Classes

  • Introduced in earlier versions of React.
  • Relies on extending the React.Component class.
  • Define lifecycle methods (e.g., render, componentDidMount) for handling component behavior at different stages.
  • Well-suited for complex components with internal state management and side effects.

Functional Components

  • Simpler and more concise syntax using JavaScript functions.
  • Return JSX to define the component’s UI.
  • Can leverage React Hooks (introduced in React 16.8) for state management, side effects, and other functionalities previously handled by class methods.
  • Currently, the preferred approach for most components due to their simplicity and alignment with modern JavaScript practices.

Functional Component with Hooks Example

import React, { useState } from 'react';

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

    const increment = () => {
        setCount(count + 1);
    };

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={increment}>Increment</button>
        </div>
    );
}

export default Counter;

Explanation

  • Line 1: Imports React and the useState hook.
  • Line 3: Defines a functional component named Counter.
  • Line 4: Uses the useState hook to create state for the counter value (count) and a function (setCount) to update it.
  • Lines 6-8: Define an increment function that increases the count by 1 using the setCount function.
  • Lines 10-15: JSX for the counter component.
    • Line 12: Displays the current count value.
    • Line 13: Button element with an onClick handler set to the increment function, triggering the count update on click.
  • Line 18: Exports the Counter component.

Choosing Wisely

While classes can be useful for complex components, functional components with Hooks are generally favored for their readability and alignment with modern React practices. For most use cases, functional components with Hooks provide a clean and efficient way to build React components.

Modern React: ES6 Features for Cleaner Code

React embraces modern JavaScript (ES6 and beyond) to empower developers to write concise and expressive code. Here’s how some features enhance React development:

Shopping Cart Component Example

import React from 'react';

class ShoppingCart extends React.Component {
    constructor(props) {
        super(props);
        this.state = { items: [] };
    }

    addItem = () => {
        this.setState({ items: [...this.state.items, { id: Math.random(), name: 'Product A', price: 10 }] });
    };

    removeItem = (itemId) => {
        const newItems = this.state.items.filter(item => item.id !== itemId);
        this.setState({ items: newItems });
    };

    render() {
        return (
            <div>
                <h2>Shopping Cart</h2>
                <ul>
                    {this.state.items.map((item, index) => (
                        <li key={item.id}>
                            {item.name} - ${item.price}
                            <button onClick={() => this.removeItem(item.id)}>Remove</button>
                        </li>
                    ))}
                </ul>
                <button onClick={this.addItem}>Add Product A</button>
            </div>
        );
    }
}

export default ShoppingCart;

Explanation

  • Line 1: Imports the React library, needed for defining React components.
  • Line 3: Defines a class component ShoppingCart extending React.Component.
  • Line 4-6: The constructor initializes component state with an empty items array.
  • Line 9-11: addItem method updates the state by adding a new item. The item ID is generated using Math.random() for uniqueness.
  • Line 13-15: removeItem method filters out the item by its ID and updates the state with the new items array.
  • Line 18-32: The render method returns JSX to display the shopping cart, including a list of items and buttons to add or remove items.
    • Line 23-28: Maps over this.state.items to display each item in a list. Uses the item’s ID as a key for each list item.
    • Line 26: Each item has a remove button that calls removeItem with the item’s ID.
  • Line 30: A button to add a predefined product to the shopping cart by calling addItem.
  • Line 36: Exports the ShoppingCart class.

Key Points

  • Arrow functions: Used in addItem and removeItem for concise function definitions.
  • Class constructors: Used in ShoppingCart to initialize component state.
  • Template literals: Used in addItem to create a new item object.
  • Destructuring assignment: Used in removeItem to create a new newItems array.
  • Spread operator: Used in addItem to add a new item to the items array.
  • Map function: Used in render to iterate over the items array.

Optional Chaining and Nullish Coalescing in React (ES6)

When dealing with potentially nested data structures in React, optional chaining (?.) and nullish coalescing (??) operators provide essential safeguards against errors. These operators enhance code safety and prevent runtime errors that might occur when accessing properties of potentially null or undefined values.

  • Optional Chaining (?.)
    • Offers a safe way to access nested properties.
    • If any part of the chain evaluates to null or undefined, the entire expression evaluates to undefined, avoiding errors.
  • Nullish Coalescing (??)
    • Provides a default value if the left-hand operand is null or undefined.
    • Useful for ensuring you always have value to work with, even when data might be missing.

Safe User Profile Display Example

import React from 'react';

function UserProfile({ user }) {
    const name = user?.name; // Optional chaining for name
    const email = user?.contact?.email ?? 'No email provided'; // Nullish coalescing for email

    return (
        <div>
            <h2>{name}</h2>  {/* Display name, or nothing if user.name is null/undefined */}
            <p>Email: {email}</p>  {/* Display email or 'No email provided' if user.contact or email is null/undefined */}
        </div>
    );
}

export default UserProfile;

Explanation

  • Line 4: Uses optional chaining to access user.name. If user is null or undefined, the expression evaluates to undefined without an error.
  • Line 5: Uses nullish coalescing to access user.contact.email. If user or contact is null/undefined, or email is null/undefined, the default value "No email provided" is used.

Key Points

  • Optional Chaining: Prevents errors by gracefully handling missing data within nested structures.
  • Nullish Coalescing: Ensures you have a value to work with, even for potentially incomplete data.
  • Improved Readability: Makes code more readable and less prone to errors.

By incorporating optional chaining and nullish coalescing in your React components, you can write more robust and user-friendly applications that gracefully handle data absence.