Getting Started with React - Lesson #17

Parent - Child React Components with Props

When working with React, we must often break down our sites and applications into multiple components. This often includes having a parent component and child components.

We can pass information to child components using props.

jsx
// 👵 parent component
<div>
    <NavLink url="/tutorials" text="Tutorials" />
</div>

// --------------------

// 👶 child component
function NavLink(props) {
    return <a href={props.url}>{props.text}</a>
}

If we had a blog, we would need an article header that had:

  • Blog Title
  • Blog Author
  • Blog Published At Date
  • Blog Tags

Let's see how we can create this with React and multiple components. We could write this with one giant component, but it could potentially get long, messy, and hard to read.

We will start with a main parent component called BlogHeader. We will write some wishful code on how we want our overall parent component and child components to look.

jsx
// import our child components 
import BlogAuthor from './BlogAuthor';
import BlogPublishedAt from './BlogPublishedAt';
import BlogTags from './BlogTags';

// normally we would get this from an api
// for this example we are just hardcoding it
const article = {
  title: "React is Awesome",
  author: {
    name: "Chris Sev",
    twitter: "chris__sev",
  },
  publisedAt: new Date(2021, 10, 14),
  tags: ["react", "javascript"],
};

function BlogHeader() {
  return (
    <div>
      <h1>{article.title}</h1>

            {/* child components */}
      <BlogAuthor />
      <BlogPublishedAt />
      <BlogTags />
    </div>
  )
}

In order to pass information down, we will bind the data as an attribute on the JSX element. We call these props.

jsx
<BlogAuthor author={article.author} />
<BlogPublishedAt publishedAt={article.publisedAt} />
<BlogTags tags={article.tags} />

We can name these anything we want. We just need to be aware of the naming and make sure we reference them correctly in each child component.

Also note, that we are able to pass down any type of information.

  • BlogAuthor gets an author object
  • BlogPublishedAt gets a Date
  • BlogTags gets an array
jsx
// BlogAuthor.js

// get props as an argument
// author is passed into props since we passed it earlier
// in the parent component: <BlogAuthor author={article.author} />

function BlogAuthor(props) {
    return (
        <>
            <div>{props.author.name}</div>
            <div>{props.author.twitter}</div>
        </>
    );
}
jsx
// BlogPublishedAt.js

function BlogPublishedAt(props) {
    return <div>Published on {props.publishedAt.toLocaleDateString()}</div>
}
jsx
// BlogTags.js

function BlogTags(props) {
  return (
    <>
      {props.tags.map((tag) => <span key={tag}>{tag}</span>)}
    </>
  )
}

Every React component has a property passed to it called props. In our BlogAuthor component, we can get the author that was passed to it like so:

jsx
// in the parent component: <BlogAuthor author={article.author} />

// child component
function BlogAuthor(props) {

    // we have our author object using props.author

}

We can also destructure props using JavaScript's object destructuring. The following examples are the same.

Destructuring props lets us write less code and make our code more readable.

jsx
function BlogAuthor(props) { ...

// is the same as

function BlogAuthor({ author }) { ...

I will 99% of the time destructure props.

It can hard to decide what should be a parent component and what should be child components. I like to use the smart vs dummy approach (also known as the presentational and container approach).

Keep in mind, this is more of a suggestion than a rule. There are many ways to split up your React components and their functionality, but I like to start with this idea.

Smart Components: The components that hold values in state and handle the big events like form submissions, fetching data, and saving data to an API/database.

Dumb Components: The components that display information. They don't have any logic to them. They just display information but don't do too much processing.

Let's say we wanted to change the layout of our article header. It's as easy as moving components around.

We are composing our UI together using multiple React components.

We can move these in any order or handle layout/CSS styling in our parent component.

jsx
<BlogAuthor author={article.author} />
<BlogPublishedAt publishedAt={article.publisedAt} />
<BlogTags tags={article.tags} />

You can pass props down to child components when using a .map().

jsx
import Person from './Person.js';

const people = [
  { name: 'chris' },
  { name: 'kapehe' }
];

function PeopleList() {
  return (
    <div>
      {/* loop over the people and pass to a Person component */}
      {people.map((person, index) => (
        <Person key={index} person={person} />
      ))}
    </div>
  )
}

// 👶 child component
function Person({ person }) {
    return <div>{person.name}</div>
}
Chris Sev

Chris Sev

Chris Sev is the co-founder of Better Dev. Coding better every day. Previously he created Scotch.io which was acquired.