React  

Building and Reusing Components in React with Props

Introduction

In React, components are the building blocks of your application. They help you break down the UI into manageable pieces. To make these components reusable and dynamic, React uses something called props.

What Are Props?

Props (short for "properties") are read-only inputs passed from a parent component to a child. They allow you to pass data and behavior into components, enabling reusability and dynamic rendering.

Think of props as function arguments, and components as functions, props let you customize what each component displays or does.

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

In the above example, props.name allows the Welcome component to display different names based on what is passed to it.

How to Use Props in React?

To use props.

  1. Define props in your child component.
  2. Pass them from the parent component using HTML-like syntax.

File Structure

📁 src/
├── 📁 components/
│   └── 📄 Card.js
│
├── 📁 data/
│   └── 📄 users.js
│
└── 📄 App.js

Card.js – Reusable Component

const Card = (props) => {
    return (
        <div style={{ border: "1px solid #ddd", padding: "1rem", margin: "1rem", 
            display: "inline-block" }}>
          <h2>{props.name}</h2>
          <p>Age: {props.age}</p>
          <p>Profession: {props.profession}</p>
        </div>
    );
};

export default Card;
  • The card is a React functional component that takes one parameter: props
  • props is a JavaScript object that is going to contain all the data that is being passed to this component from its parent.
  • {props.name} displays the value of the name prop inside an <h2>.
  • {props.age} and {props.profession} do the same for age and profession.

Using Destructuring in the Card Component

Now let's rewrite the same card component using destructuring for cleaner and more concise code.

If you want to learn more about destructuring in JavaScript, check out: Destructuring in JavaScript

Here, Instead of accessing props.name, props.age, and props.profession, we destructure those values directly in the function parameters: ({ name, age, profession })

const Card = ({ name, age, profession }) => {
    return (
      <div style={{ border: "1px solid #ddd", padding: "1rem", margin: "1rem", display: "inline-block"  }}>
        <h2>{name}</h2>
        <p>Age: {age}</p>
        <p>Profession: {profession}</p>
      </div>
    );
  };
  
export default Card;

How to Call This Component from the Parent?

You can now use the Card component in your parent component (like App.js) and pass the required props.

<Card name="Alex" age={28} profession="Engineer" />

Alex

Full Version of App.js

Below is the complete code for the App component. In this example, the App component acts as the parent, and the Card is the child component since it is being rendered (or "nested") inside Athe pp.

import './App.css';
import Card from './components/Card'

function App() {
  return (
    <div className="App">
      <Card name="Alex" age={28} profession="Engineer" />
    </div>
  );
}

export default App;

Why Is Card a Child Component?

In React, when one component renders another, the rendered component is considered a child. This structure helps organize the UI and pass data using props from parent to child.

Using External Data Instead of Hardcoded Values

So far, we've tested our card component using hardcoded values, like passing "Alex" directly. However, in real-world apps, data often comes from external sources or files. Let's simulate that by creating a separate data file.

//data/users.js

const users = [
    {
        name: "Alex",
        age : 25,
        profession : "Engineer"
    },
    {
        name: "Gloria",
        age : 23,
        profession : "Designer"
    },
    {
        name: "Martin",
        age : 25,
        profession : "DevOps"
    }
]
export default users;

We’ve now moved our user data to a separate file called users.js.

Importing and Passing Data in App.js

Now that our data is stored externally, we can import it into our App-component and pass it as props to Card.

import './App.css';
import Card from './components/Card'
import users from "./data/users";

function App() {
  return (
    <div className="App">
      <Card
        name={users[0].name}
        age={users[0].age}
        profession={users[0].profession}
      />    
    </div>
  );
}

export default App;

Here, we’re accessing the first user (Alex) from the user's array and passing their details as props to the card component. For the card component, there is no change, this component receives dynamic values via props and renders them accordingly.

Instead of passing each prop individually, you can use the spread operator to pass all properties of an object at once: This automatically spreads all key-value pairs (like name, age, and profession) from the user object into the Card component as props.

<Card {...users[1]} /> 

Output

Rendering Multiple Users with .map()

{
  users.map((user, index) => (
  <Card key={index} {...user} />
  ))
}

This code dynamically renders a Card for every user in the array. By using the spread operator, the code stays scalable even as your data grows.

Result

Let's touch on Destructuring in detail.

Destructuring lets you extract values from an object or array.

Without Destructuring

function Card(props) {
  return <h2>{props.name}</h2>;
}

With Destructuring

function Card({ name }) {
  return <h2>{name}</h2>;
}

You can also set default values.

function Card({ name = "Guest" }) {
  return <h2>{name}</h2>;
}

Common Mistakes to Avoid

Mistake Why it's a problem
Passing props that aren't used This leads to unnecessary re-renders and confusion
Forgetting key in lists React needs unique key props for dynamic lists
Destructuring a non-existent property Results in undefined or runtime errors
Modifying props inside child components Props are read-only; use state instead
Assuming all data will always be present Use default values or conditional rendering
Using complex expressions directly in JSX Makes JSX hard to read; better to use variables

Best Practices & Norms to Follow

Best Practice Why it helps
Destructure props in the function parameter Cleaner, more readable code
Use default values when destructuring Prevents undefined rendering
Validate prop types with PropTypes (optional) Helps catch type-related bugs
Use the spread operator carefully Ensure only valid and expected props are passed
Use key prop when rendering lists Prevents rendering bugs in dynamic lists
Keep components focused and small Easier to reuse, test, and maintain

Conclusion

React props make components reusable, and dynamic. By understanding different ways of passing props, manually, via array indexing, or using the spread operator and applying destructuring, you can write cleaner and more maintainable React code.

By avoiding common mistakes and following best practices, you'll build components that are easier to read, debug, and reuse across your projects.