Passing Props Between Components

Loading

Props (short for properties) are React’s mechanism for passing data between components. They flow unidirectionally from parent to child components and are immutable (child components cannot modify their props).

1. Basic Prop Passing

Parent → Child (Direct Passing)

// Parent Component
function Parent() {
  return <Child name="Alice" age={25} />;
}

// Child Component
function Child(props) {
  return (
    <div>
      <p>Name: {props.name}</p>
      <p>Age: {props.age}</p>
    </div>
  );
}

Destructuring Props (Cleaner Syntax)

function Child({ name, age }) {
  return (
    <div>
      <p>Name: {name}</p>
      <p>Age: {age}</p>
    </div>
  );
}

2. Passing Different Data Types

Strings, Numbers, Booleans

<User name="Bob" age={30} isAdmin={true} />

Arrays & Objects

<TodoList items={["Task 1", "Task 2"]} user={{ id: 1, name: "Alice" }} />

Functions (Callbacks)

// Parent
function Parent() {
  const handleClick = () => console.log("Button clicked");
  return <Child onButtonClick={handleClick} />;
}

// Child
function Child({ onButtonClick }) {
  return <button onClick={onButtonClick}>Click Me</button>;
}

JSX/Components (Children Prop)

<Card>
  <h2>Title</h2>
  <p>Content goes here</p>
</Card>

// Card component implementation
function Card({ children }) {
  return <div className="card">{children}</div>;
}

3. Prop Drilling & Alternatives

Prop Drilling (Passing Through Multiple Layers)

function App() {
  const [user, setUser] = useState("Alice");
  return <Header user={user} />;
}

function Header({ user }) {
  return <Profile user={user} />;
}

function Profile({ user }) {
  return <div>Current user: {user}</div>;
}

Alternatives to Prop Drilling

  1. Context API – For global data
  2. State Management (Redux, Zustand) – For complex state
  3. Component Composition – Using children props

4. Type Checking with PropTypes

import PropTypes from 'prop-types';

function User({ name, age }) {
  return (
    <div>
      <p>Name: {name}</p>
      <p>Age: {age}</p>
    </div>
  );
}

User.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number
};

User.defaultProps = {
  age: 18
};

5. Common Patterns

Conditional Rendering Based on Props

function Greeting({ isLoggedIn }) {
  return isLoggedIn ? <WelcomeMessage /> : <LoginPrompt />;
}

Mapping Props to Components

function UserList({ users }) {
  return (
    <ul>
      {users.map(user => (
        <UserItem key={user.id} name={user.name} />
      ))}
    </ul>
  );
}

6. Best Practices

  1. Keep props minimal – Only pass what’s needed
  2. Use descriptive prop names – Avoid generic names like “data”
  3. Avoid mutating props – Treat them as read-only
  4. Use TypeScript for better type safety (alternative to PropTypes)
  5. Document props with comments or Storybook

7. Advanced Patterns

Render Props

<DataFetcher
  render={data => <UserList users={data} />}
/>

function DataFetcher({ render }) {
  const [data, setData] = useState(null);
  // Fetch data...
  return render(data);
}

Higher-Order Components (HOCs)

function withAuth(Component) {
  return function AuthenticatedComponent(props) {
    const isAuthenticated = checkAuth();
    return isAuthenticated ? <Component {...props} /> : <LoginPage />;
  };
}

const ProtectedProfile = withAuth(Profile);

Key Takeaways

  1. Props enable parent-to-child communication
  2. They can pass any JavaScript value (including components)
  3. Props are read-only in child components
  4. For complex applications, consider context or state management to avoid prop drilling

Leave a Reply

Your email address will not be published. Required fields are marked *