State, props and Hooks

State, props and Hooks

Dynamic Content in React Components

·

6 min read

So far, we have learned about components. Now let's explore how to add and manage dynamic content in components.

What is State in React?

State in React is an object that contains information about the component, including its properties and their values.

For example:


function Student() {
    const studentState = {
        name: 'Dheeraj',
        age: 21
    };

    return (
        <h2>Hello, I'm {studentState.name} and I'm {studentState.age} years old.</h2>
    );
};

export default Student;

Now you can manage and manipulate the state using the useState hook, which we will discuss later in this blog.

What are Props in React?

Props refer to properties that can be passed to a child component as arguments. It allows us to customize the behavior of a component. Let's take an example to understand this concept.

In the previous example, we created the Student component, where the data was static. However, if we want to display different names and ages for the Student component, we can achieve this using props.

Let's modify the Student component and create a new component called StudentList.

Student Component

import React from 'react';

function Student(props) {

    return (
        <h2>Hello, I'm {props.student.name} and I'm {props.student.age} years old.</h2>
    );
};

export default Student;

StudentList Component

import React from 'react';
import Student from './Student';

function StudentList() {

    const studentList = [
        {
            name: 'Dheeraj',
            age: 21
        },
        {
            name: 'Suraj',
            age: 25
        }
    ]

    return (
        <ul>
            {
                studentList.map(student => {
                    return (
                        <li>
                            <Student student={student} />
                        </li>
                    );
                })
            }
        </ul>
    );
};

export default StudentList;

student-list

Hooks in React

Hooks in React are functions that are used to manipulate the state and perform actions when there is a change in the component's lifecycle. As mentioned earlier, we will now discuss the useState hook.

useState Hook

The useState hook is used to manage and manipulate the state of a React component. It returns an array containing two elements:

  1. Getter Variable: A variable that allows us to access the state.

  2. Setter Function: A function that is used to change the state.

Let's see an example by making changes to the StudentList component:

import React, { useState } from 'react';
import Student from './Student';

function StudentList() {

    const studentList = [
        {
            name: 'Dheeraj',
            age: 21
        },
        {
            name: 'Suraj',
            age: 25
        }
    ]

    const [showStudents, setShowStudents] = useState(false);

    function changeShowStudents() {
        setShowStudents(!showStudents);
    }

    if (!showStudents) {
        return (
            <button onClick={changeShowStudents}>Show Students</button>
        );
    } else {
        return (
            <>
                <button onClick={changeShowStudents}>Hide Students</button>
                <ul>
                    {
                        studentList.map(student => {
                            return (
                                <li>
                                    <Student student={student} />
                                </li>
                            );
                        })
                    }
                </ul>
            </>
        );
    }
};

export default StudentList;

In the above code, useState(false) returns an array where showStudents is a variable representing the current value of the state, and setShowStudents is a function used to update the state.

dynamic-state

dynamic-state-update

Here, using the useState hook, we dynamically changed the showStudents state.

useEffect Hook

Before we discuss the useEffect hook, let's understand the lifecycle phases of a React component:

React Component Lifecycle

A component goes through the following phases:

  1. Mounting: When the component is added to the DOM for the first time.

  2. Update: When there is a change in the component's state or props.

  3. Unmounting: When the component is removed from the DOM.

The useEffect hook is called whenever there is a side effect (mounting, update, or unmounting). It takes two arguments: a callback function that describes what to do when there is a side effect, and an array of variables that the hook should watch for changes.

The useState hook should be used when you need a dynamic variable that affects your UI logic or causes UI changes.

The useEffect hook should be used to detect any changes in the component lifecycle.

For example:

import React, { memo, useEffect } from 'react';
import ProductCard from '../ProductCard';
import styles from './ProductList.module.css';
import { useDispatch, useSelector } from 'react-redux';
import { loadingProducts } from '../../Store/Products';

function ProductList({ categoryId }) {

    console.log('ProductList rendered');

    const dispatch = useDispatch();
    const products = useSelector(state => state.productList);

    useEffect(() => {
        dispatch(loadingProducts(categoryId));
    }, [categoryId, dispatch]);

    if (!categoryId) {
        return <div>Select a Category</div>;
    } else if (products.isLoading) {
        return <div>Loading...</div>;
    } else if (products.products.length > 0) {
        return (
            <div className={styles.list}>
                {products.products.map(product => (
                    <ProductCard key={product.id} product={product} />
                ))}
            </div>
        );
    } else {
        return <div>No products found. Choose a different category.</div>;
    }
};

export default memo(ProductList);

This code is a React component called ProductList that renders a list of products based on the provided categoryId. Here's a breakdown of the code:

  1. The component imports necessary dependencies from React, such as React, memo, and useEffect, and also imports the ProductCard component.

  2. It imports the CSS module ProductList.module.css for styling.

  3. The component uses the useDispatch and `use

Selectorhooks fromreact-reduxto interact with the Redux store. 4. TheProductListcomponent receives acategoryIdprop. 5. The component defines adispatchvariable to dispatch actions to the Redux store and usesuseSelectorto select theproductListstate from the store. 6. The component uses theuseEffecthook to dispatch theloadingProductsaction when thecategoryIdordispatchdependencies change. This action is responsible for fetching the products based on the providedcategoryId`. 7. Inside the component, there are conditional rendering statements:

  • If categoryId is not provided, it returns a message asking to select a category.

  • If the products.isLoading flag is true, it returns a loading message.

  • If there are products available, it renders a list of ProductCard components using the products.products array. Each ProductCard component receives a unique key prop and the corresponding product object.

  • If there are no products available, it returns a message indicating that no products were found in the selected category.

  1. The ProductList component is exported using memo to optimize performance by memoizing the component and preventing unnecessary re-renders.

Overall, this component fetches and renders a list of products based on the provided category ID, displaying loading messages or appropriate feedback based on the loading status and availability of products.

When we want to run useEffect only on the first render, we pass an empty array as the dependency.

A Surprise Content at the End

Virtual DOM

  • Whenever we make a change in the DOM, it incurs a significant cost. In a complex application, there can be numerous changes made.

  • To minimize this cost, React uses a concept called the Virtual DOM.

  • The Virtual DOM is a virtual representation of the real DOM, represented in JSON format.

For example, let's create a component:

function App() {
    return (
        <ul className="list">
            <li>
                <a className="item-1">Item 1</a>
            </li>
            <li>
                <a>Item 2</a>
            </li>
            <li>
                <a>Item 3</a>
            </li>
        </ul>
    );
}

The structural tree of the component would look like this:

virtual-dom-tree

And the JSON representation would be:

let vdom = {
    nodeName: "ul",
    properties: {
        className: "list",
        children: [
            {
                nodeName: "li",
                properties: {
                    children: [
                        {
                            nodeName: "a",
                            properties: {
                                className: "item-1",
                                children: ["Item 1"]
                            }
                        }
                    ]
                }
            },
            {
                nodeName: "li",
                properties: {
                    children: [
                        {
                            nodeName: "a",
                            properties: {
                                children: ["Item 2"]
                            }
                        }
                    ]
                }
            },
            {
                nodeName: "li",
                properties: {
                    children: [
                        {
                            nodeName: "a",
                            properties: {
                                children: ["Item 3"]
                            }
                        }
                    ]
                }
            }
        ]
    } 
}

How Virtual DOM Works

  1. React maintains two versions of the Virtual DOM: the current Virtual DOM and the updated Virtual DOM.

  2. When there is an update, React uses an algorithm to determine the changes.

  3. Instead of updating the entire DOM, React only makes changes to the specific part of the DOM where the update occurred.

  4. This approach ensures that only the necessary parts of the DOM are re-rendered, improving performance.

Conclusion

I hope you found this blog post helpful. Please like and share it if you did.

Thank you!

Did you find this article valuable?

Support DevWithAvatar by becoming a sponsor. Any amount is appreciated!