Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 12

Setting Default Prop Values

Recommended resources

Welcome back! In our last lesson, we learned how to make our components dynamic by passing data from a parent to a child using props. We also established a critical rule: props are read-only.

This leads to a natural question: what happens if a parent component forgets to pass a required prop? This could lead to undefined values in your child component, potentially causing bugs or a broken UI.

In this lesson, we will tackle that exact problem. Our goal is to learn how to define default values for props to prevent errors. By providing sensible defaults, we can make our components more robust and predictable.

The Problem: When Props Go Missing

Imagine a UserProfile component that expects to receive a name and an avatarUrl to display a user's profile picture.

// A component expecting two props
const UserProfile = ({ name, avatarUrl }) => {
  return (
    <div className="user-profile">
      <img src={avatarUrl} alt={`Avatar for ${name}`} />
      <p>{name}</p>
    </div>
  );
};

If we use this component and provide all the props, everything works perfectly:

<UserProfile name="Alex" avatarUrl="https://example.com/alex.jpg" />

But what if a developer forgets to pass the avatarUrl?

<UserProfile name="Alex" />

In this case, avatarUrl inside the UserProfile component will be undefined. The browser will try to render an <img> with src="undefined", resulting in a broken image icon. This is not a great user experience. We need a fallback.


The Solution: Default Parameters

Since you're familiar with modern JavaScript (ES6), the solution is straightforward and elegant. You can set a default value for a prop directly within the function signature where you destructure it. This is the recommended and most common way to handle default props in modern React.

The syntax is simple: const MyComponent = ({ propName = defaultValue }) => { ... }.

Let's fix our UserProfile component using this pattern:

// path: src/components/UserProfile.jsx

const UserProfile = ({ name, avatarUrl = "/default-avatar.png" }) => {
  // If avatarUrl is not passed, it will automatically be "/default-avatar.png"
  return (
    <div className="user-profile">
      <img src={avatarUrl} alt={`Avatar for ${name}`} />
      <p>{name}</p>
    </div>
  );
};

Now, if we render <UserProfile name="Alex" />, the component will use the default image path, preventing a broken UI. If we render <UserProfile name="Alex" avatarUrl=".../alex.jpg" />, the passed prop will override the default.

Let's read the official React documentation to solidify this.

Passing Props to a Component

The official React docs provide a concise and clear explanation of specifying default values using destructuring. It's the best place to start.

Read the section titled 'Specifying a default value for a prop'. Pay close attention to the syntax and the important note about when the default value is used (and when it is not).

As the documentation highlights, this is a crucial point:
The default value is only used if the prop is missing or its value is undefined. If you explicitly pass prop={null} or prop={0}, those values will be used, and the default will be ignored.


An Important Note on Outdated Patterns

As you browse older tutorials, company codebases, or Stack Overflow answers, you will almost certainly encounter another way of setting default props: the defaultProps static property.

// The OLD way - do not use for new functional components
function Button({ label, color }) {
  // ...
}

Button.defaultProps = {
  label: 'Click Me',
  color: 'blue'
};

This pattern was common for both class and functional components. However, it's important for you to know that defaultProps on functional components is being deprecated and will be removed in a future major version of React.

To understand why this change is happening and see a clear demonstration of the modern approach, the following video is very insightful.

Stop using defaultProps (React 18.3 preview)

Matt Pocock, a well-known developer in the React/TypeScript community, explains the deprecation of defaultProps for functional components and clearly demonstrates the modern, recommended alternative.

Watch from the beginning to 02:37. Focus on: The announcement that defaultProps is deprecated for function components (0:00 - 0:51). The demonstration of the console warning this will produce (0:51 - 1:55). The clear explanation of how to correctly use JavaScript's default parameters as the replacement (1:55 - 2:37).

The key takeaway is that using default parameters in the function signature is more aligned with modern JavaScript, is cleaner, and works better with tools like TypeScript. While you should recognize defaultProps when you see it, always use the default parameter syntax in your own new components.


Let's Practice

Let's apply this to a component we've already worked with. In the previous lesson, your Header component received a title prop. Let's make it more robust.

  1. Modify Header.jsx: Update your Header component to use a default value for the title prop. If no title is provided, it should default to "My Awesome App".

  2. Modify App.jsx: To test this, render two Header components:

    • One with the title prop explicitly set to something new, like "Learning Props".
    • One with no title prop passed at all.

This will let you see both the override and the default value in action.

Click to see the solution for `Header.jsx`
// src/components/Header.jsx

const Header = ({ title = "My Awesome App" }) => {
  return (
    <header style={{ backgroundColor: '#f8f9fa', padding: '1rem', textAlign: 'center' }}>
      <h1>{title}</h1>
      <p>Learning about default props!</p>
    </header>
  );
};

export default Header;
Click to see the solution for `App.jsx`
// src/App.jsx

import Header from './components/Header';
import Footer from './components/Footer';
import './App.css';

function App() {
  return (
    <>
      {/* This Header will use the passed prop */}
      <Header title="Learning Props" />
      
      {/* This Header will use the default prop */}
      <Header />

      <main>
        <p>This is the main content of my application.</p>
      </main>
      <Footer />
    </>
  );
}

export default App;

Conclusion

You've now learned how to make your components more resilient and predictable. Defining default props is a simple but powerful technique that prevents errors and clarifies how a component is intended to be used, especially when some props are optional.

Key Takeaways:

  • Purpose: Default props provide fallback values when a prop is not passed, preventing undefined-related errors.
  • Modern Syntax: The recommended way to set default props is using JavaScript's default parameter syntax directly in the component's destructuring signature: ({ prop = 'default value' }).
  • Deprecation: The Component.defaultProps static property is deprecated for functional components. You should recognize it but not use it for new code.
  • Behavior: A default value is only applied if a prop is undefined (i.e., missing or explicitly passed as undefined). It is not used for null, 0, false, or empty strings "".

Next Up:

So far, we've passed specific, named pieces of data like strings and numbers. But what if we want to pass a larger, more complex chunk of UI from a parent to a child? In the next lesson, we will explore component composition and the special children prop, which allows you to create highly flexible and reusable wrapper components.