DEV Community

Cover image for Understanding useState Hook, Props and Prop Drilling, In React
Opeyemi Odunayo
Opeyemi Odunayo

Posted on

Understanding useState Hook, Props and Prop Drilling, In React

In this article, you will get to understand props, prop drilling, and the useState hook in react, just sit back, relax and enjoy the reading

Usestate Hook

Every React component can have its own state.
What do we mean by state? The state is the set of data that is managed by the component.
Think about a form, for example. Each individual input element of the form is responsible for managing its state: what is written inside it.
A link is responsible for knowing if the mouse is hovering over it.
In React, or in any other components-based framework/library, all our applications are based and make heavy use of components state.
We manage state using the useState utility provided by React. It's
technically a hook (you don't need to know the details of hooks right now, but that's what it is).
You import useState from React in this way:

import React, { useState } from 'react'
Enter fullscreen mode Exit fullscreen mode

Calling useState(), you will get back a new state variable, an a function that we can call to alter its value. useState accepts the initial value of the state item and returns an array containing the state variable, and the function you call to alter the state.
Example:

const [count, setCount] = useState(0)
Enter fullscreen mode Exit fullscreen mode

This is important. We can't just alter the value of a state variable directly. We must call its modifier function. Otherwise, the React component will not update its UI to reflect the changes in the data. Calling the modifier is the way we can tell React that the component state has changed. The syntax is a bit weird, right? Since useState() returns an array we use
array destructuring to access each individual item, like this:
const [count,setCount] = useState(0)
Let's assuming we're building a simple react counter app, we can just start by setting the initial state to 0
Here's a practical example:

import { useState } from 'react'
const Counter = () => {
 const [count, setCount] = useState(0)
 return (
 <div>
 <p>You clicked {count} times</p>
 <button onClick={() => setCount(count + 1)}>Click me</button>
 </div>
 )
}
ReactDOM.render(<Counter />, document.getElementById('app'))
Enter fullscreen mode Exit fullscreen mode

In the above React counter app, the counter's initial state is set to 0 using the count variable let [count] = useState(0), to update the count state we can achieve that by pressing the click me button which will triggered the setCount variable and update the count state in respect to the logic in the onclick function
You can add as many useState calls you want, to create as many state variables as you want

const [count, setCount] = useState(0)
const [anotherCounter, setAnotherCounter] = useState(0)
Enter fullscreen mode Exit fullscreen mode

Props

Prop is short for Property in React it actually refers to a piece of data that is passed from a parent component to a child component
here is a code snippet example

// ParentComponent.js
import React from 'react';
import ChildComponent from './ChildComponent';

function ParentComponent() {
  const [myName, setMyName] = React.useState("john");

  return (
    <div>
      <h2>Parent Component</h2>
      <ChildComponent message={message} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In the above code the ParentComponent renders a div containing an h2 heading and a ChildComponent. The ParentComponent maintains a state variable message, which is passed to the ChildComponent as a prop named message. This allows data to be passed from the parent component to its child component.

Prop drilling
Prop drilling is a straightforward concept. Suppose you have a hierarchy of components, with a parent component at the top and multiple levels of child components beneath it. If the parent component has some data that needs to be accessed by one of its distant descendant components, it can pass that data down through its child components as props, each intermediate child component in the hierarchy receives the data as a prop and passes it down further until it reaches the component that needs it. This process of passing props down the component tree is known as prop drilling

Example of Prop Drilling

Consider a simple React application with three components: ParentComponent, ChildComponent, and GrandchildComponent. The ParentComponent has some data that needs to be accessed by the GrandchildComponent.

// ParentComponent.js
import React from 'react';
import ChildComponent from './ChildComponent';

function ParentComponent() {
  const [message, setMessage] = React.useState("Hello from Parent");

  return (
    <div>
      <h2>Parent Component</h2>
      <ChildComponent message={message} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Above, ParentComponent holds the data in its state and passes it down to the ChildComponent as a prop.

// ChildComponent.js
import React from 'react';
import GrandchildComponent from './GrandchildComponent';

function ChildComponent({ message }) {
  return (
    <div>
      <h3>Child Component</h3>
      <GrandchildComponent message={message} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

The ChildComponent then passes the data down further to the GrandchildComponent

in a real world scenario to make it more comprehensive we built a small app ( filtering app ) that uses the filtering method in Array where we use a particular function removePerson().

let data = [
  { id: 1, name: "opeyemi" },
  { id: 2, name: "odunayo" },
  { id: 3, name: "emmanuel" },
  { id: 4, name: "john" }
]


function PropDrilling() {
  let [people, setPeople] = useState(data)


  let removePerson = (id) => {
    let newPeople = people.filter((person) => person.id !== id)
    setPeople(newPeople)
  }
  return (
    <section>
      <h3>Prop Drilling</h3>
      <List people={people} removePerson={removePerson} />
    </section>
  )

Enter fullscreen mode Exit fullscreen mode

In the above code we created a state of an array and passed it as a prop to a List component and a function newPeople() which we also pass as a prop it the component

Prop drilling occurs when you have multiple components and you have a big component tree and then you need to start passing some state from the top component all the way to the bottom component. The code below illustrates it better

function PropDrilling() {
  let [people, setPeople] = useState(data)
  let removePerson = (id) => {
    let newPeople = people.filter((person) => person.id !== id)
    setPeople(newPeople)
  }
  return (
    <section>
      <h3>Prop Drilling</h3>
      <List people={people} removePerson={removePerson} />
    </section>
 )
}
Enter fullscreen mode Exit fullscreen mode

In the code above we have our parent component PropDrilling, we have a people’s state in the component which we pass into our
list component as a prop, and the removePerson function is defined to remove a person from the people state array which we also pass into the List component as a prop

let List = ({ people, removePerson }) => {
  return (
    <>
      {people.map((person) => {
        return <SinglePerson key={person.id} {...person}
          removePerson={removePerson} />
      })}
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

In the above code we destructure the people’s array then map and spread the people’s object in a SinglePerson component, we also destructure the removePerson() function and pass it as a prop into the component

let SinglePerson = ({ id, name, removePerson }) => {
  return (
    <div style={{
      padding: "0 4px", margin: "20px auto", maxWidth: "500px",
      display: "flex", alignItems: 'center', justifyContent:         
     'space-between',
      background: "#333", color: 'white'
    }}>
      <h3>{name}</h3>
      <button style={{
        border: "none", color: "#fff", background: "none",
        height: "50px"
      }} onClick={() => removePerson(id)}> remove</button>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Lastly, we destructure the object and removePeople() then finally make use of it in the SinglePerson component. Inside the JSX, it renders each person's name along with a button to remove that person When the button is clicked, it calls the removePerson() with the person's id. so the overview of this prop drilling is that we have a state and a function which we pass down from the parent tree to the last component where we actually needed them.

Conclusion

Prop drilling is a simple yet effective way to pass data between components in React. While it works well for small to medium-sized applications, it can become cumbersome in larger applications with deeply nested component trees. In such cases, other state management solutions like Context API or Redux may be more suitable. However, understanding prop drilling is fundamental to grasping how data flows in React applications. By mastering prop drilling, developers can build more efficient and maintainable React applications. ok its not baad

so far so good you've made it to the end of this article on state, props, and prop drilling in React by now you should have a solid understanding of what state, props, and prop drilling are and how to use them effectively in your react component

Top comments (0)