Understanding How Props Are Passed to React Component

Note: This is part 2 of three-part prerequisite post series. A  prior knowledge of these topics is essential before deep diving into Creating List React component.

In the previous learning-note post Learning to Work With React Components, how to build a simple react component using run time <script>in a HTML file were discussed. Although slow, this approach is not ideal for react app development, however it is ideal for my current learning purposes.

The purpose of this learning-note post is understand how to build a simple list react component and apply that knowledge to build BlogPost component to list posts in a page.

JavaScript Prerequisite

Because creating List component ReactJS is advanced topic, it requires working JS knowledge in the following areas:

Post Series
Part 1: JavaScript Fundamentals – Array.Map(), Arrow Functions & Functions
Part 2: How to Pass Props (Data Objects) to Component in ReactJS (this post)
Part 3: Creating List Component in reactJS

In this Part 2 of three parts series, what are props and how props objects are used to pass data from from one component to other is discussed.

React Component – A Review

In previous post Learning React – A Basic Overview commonly used JSX terms like JSX rendering elements, HTML attributes, embedding expression in JSX and React components (Functional and Class) were discussed briefly.

1. Functional Components

Functional components are simple JS functions. A simple react component can be created with function which contains some JSX statements as shown below:

//functional component
function HelloWorld() {
    return <h1>Hello, World!</h1>;
}

Functional components are not aware of other components (eg. state) and are suitable for stateless component. Multiple functional components can be combined with a single parental component. Functional components can’t received data from other components.

2. Class Components

Revisiting Class components discussed in previous post, unlike functional components Class components are slightly complex and are aware of other components (eg state). Class component return JSX elements using (required) render() method.

// class component
class HelloWorld extends React.Component {
  render(){
    return <h1>Hello, World!</h1>;
  }
}

The above two examples of components perform exactly same. Since the Class components are aware of state work, receive data from other components and pass data from one component to other.

3. Component Rendering

React renders JSX element to DOM node by passing both the element and “root” DOM node to ReactDOM.render() as shown below:

//basic render() syntax
ReactDOM.render(element, container[, callback])

//element rending to DOM
const helloworld = <h1>Hello, world!</h1>;
ReactDOM.render(helloworld, document.getElementById('root'));

//OUTPUT
Hello, World!

In the example above, helloworld element (line 5) is pass to “root” DOM node container (line 6) which displays Hello, World! in the browser (line 9).

React also renders pre-defined components to ReactDOM.render() method by passing as  as first parameter.

//syntax to initialize component to an element
const welcome = <HelloWorld />;

//call ReactDOM
ReactDOM.render( 
    {welcome},  
    document.getElementById("root") 
);

In the example above, pre-defined HelloWorld components is initialized to an element named welcome (line 2). The component is passed into ReactDOM as {welcome} JSX expression as the first parameter (line 6) which calls

//functional component
function HelloWorld() {
    return <h1>Hello, World!</h1>;
}

//render component
ReactDOM.render( 
    <HelloWorld />,  
    document.getElementById("root") 
); 

//OUTPUT
Hello, World!

In the above example, the ReactDOM.render() is called with HelloWorld component as first parameter, then react calls the HelloWorld component (lines: 2-4) returning <h1>Hello, World!</h1>; to “root” DOM node (line 9) and displaying Hello, World! in the browser (line 13).

4. Complex Components

In previous post Learning to Work With React Components, creating more complex components,  composing & splitting component into smaller components was discussed in detail.

Read More: Learning to Work With React Components

Props

At the beginning, props can be confusing. The React document describes <strong>props</strong> as ” inputs to a React component. They are data passed down from a parent component to a child component.” From vanilla JS perspective, the react props are similar to global variables or objects.

1. Basic Syntax

How to pass  data to React components? The following steps illustrates passing data in functional components:

a. Define Data With JSX Syntax

It is pass through using JSX syntax as attributes as shown below:

//comp props
<HelloWorld someData={data.value} />

In the above example HelloWorld is a component and someData is an attribute. The data inside curly braces { } are expressions that must return value.

b.  Access the Data via Props

The data are accessed through props in defined component.

//react component
const HelloWorld = props => {
  <p>{props.someData}</p>
};

In the above example, someData attribute is accessed via props in the HelloWorld component (line 5).

Read More: Embedding Expression in JSX

c.  Rendering to React DOM

The HelloWorld Component is pass to the ReactDOM render() function, and the parameter which returns the HTML bulbs to each component.

2. Class Component

In class components, data are passed via props by defining attributes.

// syntax for declaring attributes
<ExampleComponent exampleProp = "HelloProp" />

//syntax for accessing props
this.props.exampleProp;

In the example above, exampleProp prop with a value of "HelloProp" is passed to the ExampleComponent component (line 2).

A user-defined props can be accessed from inside a component class with this.props.exampleProp syntax (line 5). From vanilla JS perspective, the this.props is global object which stores components properties (props) and the props name (eg. exampleProp) serves as object keys.

Tip: The functional components can access props directly as parameter and DO NOT need 'this' keyword. In Class components, the 'this.props' keyword syntax is required to access props.

Use Case Examples

Simple use cases of passing props data in functional components, Class components and passing default information with default props is illustrated below.

1. Passing Props Data with Components

In the following two examples, use of props to pass data (discussed in previous section) in functional as well as Class components is demonstrated.

// define functional component with props
function WelcomeComp(props){ 
  return( 
    <div> 
      {/*access data from props */} 
      <h2>Welcome to {props.siteTitle}</h2> 
      <p>I am from Functional component!</p> 
    </div> 
  ); 
} 

ReactDOM.render( 
  // pass props value with component
  <WelcomeComp siteTitle = "React Blog" />,  
  document.getElementById("root") 
);

In the example above, a functional component named WelcomeCom with props is defined (lines: 2-10). In line 6, a prop named siteTitle is defined using props.siteTitle syntax as JSX attribute. The siteTitle prop access its value "React Blog" passed to the WelcomeCom component  in line 14. As also noted earlier, in functional components, props can access prop without the this keyword.

In the example below, the same WelcomeCom component is defined using Class component with props as shown below:

//using Class components
class WelcomeCom extends React.Component{ 
  render(){ 
      return( 
        <div> 
          {/*access data from props */} 
          <h2>Welcome to {this.props.siteTitle}</h2> 
          <p>I am from Class component</p> 
        </div> 
      ); 
  } 
}
 
ReactDOM.render( 
  // pass props value with component 
  <WelcomeCom siteTitle = "React Blog" />,  
  document.getElementById("root") 
);

In Class components, unlike functional components (line 6), this keyword is required to access props data with this.props.siteTitle syntax (line 23), where siteTitle is name of the prop.

The WelcomeComp defined with either function (lines: 6) or with Class (lines: 23) display exactly the same output shown below:

Figure: Screenshot of WelcomeCom functional (A) and class (B) component rendered (left) and React console output (right).

In the screenshot above, browser outputs of WelcomeCom component with Functional & Class component is shown (left). The React DevTools inspector output (right) shows stored value of this.props.siteTitle (for Class) or props.siteTitle (for functional) as React Blog.

2. Passing Props Data with Class Components

In the previous section, how to pass and access data via props in a component was discussed.  One of the main features of react component is that react component can refer to other components.

// Define primary (parent) component 
class BlogPosts extends React.Component{ 
  render(){ 
      return( 
        <div> 
          <h2>REACT BLOG</h2> 
          <Posts author="Adam Levin" postId = "4243"/> 
        </div> 
      ); 
  } 
} 
// define secondary (child) component
class Posts extends React.Component{ 
  render(){ 
    console.log(this.props); 
     return( 
       <div> 
         <h2>Welcome to React Blog Home</h2>
	 <p>Written by: {this.props.author} | Post ID: {this.props.postId}</p>
         <p>Welcome to React Blog. This your first post. 
         Edit or delete it, then start writing.</p> 
       </div> 
     ); 
  } 
} 
ReactDOM.render( 
  // passing props 
  <BlogPosts />,  
  document.getElementById("root") 
);

In the example below, using two components (primary and secondary), passing data from primary (parent) component to secondary (child) component as props is demonstrated. The  author and postId data passed in BlogPosts component (line 7) is accessed in child component Posts via props (line 19). To better understand what is actually is stored in this.props in Posts component (line 19)  an extra console.log statement is added (line 15).

Figure: Screenshot of rendered BlogPosts component in browser (left) and browser console showing props object data passed (right).

The above screenshot of react output shows author & postId information from BlogPosts component is passed to Posts (child) component. The React DevTools inspector output (right) shows stored value for this.props (line 19).

The output of Console.log in the browser confirm that this.props is an object and contains both author & postId props pass to the Posts component (shown below).

//console.log output (line 15)
object { author: "Adam Levin", postId: "4243" }
3. Passing Props Data with Nested components

Passing props (eg. data or information, etc) from one component to another component is considered as one of the main highlights of the react component.

//define post data
const postData = {
  title: 'My song title',
  author: 'Blake Shelton',
  gendre: 'Country',
  text: 'Contrary to popular belief, Lorem Ipsum is not simply random text.'
 };
 //initialize Heading Component
const Heading = props => {
 // console.log(props);
  return (
    <h1>{props.siteTitle}</h1>
  );
};
 //initialize Posts Component
const Posts = props => {
 // console.log(props);
  return (
    <div>
      <h2>{props.title}</h2>
	  <p>Written by: {props.author} | Gendre: {props.gendre}</p>
      <p>{props.text}</p>
    </div>
  );
};
 //initialize Blog (container) Component
const Blog = props => {
  return (
    <div>
      <Heading siteTitle="React Blog" />
	  <Posts 
	     title={postData.title} 
	     author={postData.author} 
	     gendre={postData.gendre} 
	     text={postData.text}/>
    </div>
  );
};

ReactDOM.render(
  <Blog />,
  document.getElementById("root")
);

In the example above, some dummy data are defined in postData as object with four properties (lines: 2-7). Two react components Heading (lines: 9-14) and Posts (lines: 16-25) are defined as functional components using ES6 arrow function.

In Heading component, props object is used to render siteTitle value as props.siteTitle (line: 12) which will be passed from siteTitle = "React Blog" value (line 30).

Likewise, title, author, gendre and text values (lines: 20-22) from postData (lines: 2-7) are passed to Posts components with props object.

In Blog component (a container) the Heading and Posts components are returned (lines: 30-35) and the props values are passed.

The Blog component is rendered (lines: 40-43) to ReactDOM node in a div container root (line 42).

Figure: Screenshot of rendered Blog component in browser (left) and browser console showing props object passed data to Blog component (right).

The above screenshot (right) shows console.log output of Heading component (line 10) where the props.siteTitle is an object and logs its value as “React Blog“. Likewise the console.log output of Posts component (line 17) shows that the props is an object which contains the values passed values (lines: 20-22).

The following flow chart explains how props data are processed and passed to react components. The chart was inspired by Trey Alexander Davis’s Handling Data with Props in React.

Figure: Screenshot (left) showing code explanation (red) and data-flow (green) diagram (right). Flow diagram inspired by this article.

Passing Default Props to Components

The React Guide defines defaultProps as “a property on the component class itself, to set the default props for the class. This is used for undefined props, but not for null props.

In the following Greetings component with props is defined (lines: 2-4). A props named name is defined with props.name (line 2). The name props access its value "John" passed to the Greetings component (line 7) and renders expected output Hello, John (line 11).

//functional component
function Greetings(props) {
    return <h1>Hello, {props.name}</h1>;
}
//pass props
ReactDOM.render( 
    <Greetings name="John" />  
    document.getElementById("root") 
);
//OUTPUT
Hello, John

In the above example, if prop name is not defined (line 15, as shown in example below) what happens? The browser outputs as undefined (line 19).

//pass props
ReactDOM.render( 
    <Greetings  />  
    document.getElementById("root") 
);
//OUTPUT
Hello, unidentified

This type of problems can be solved by passing a default value for props, in case it is not defined.

// Class Component 
class BlogTitle extends React.Component{ 
    render(){ 
      return( 
          <div> 
            {/* define default prop - siteTitle */} 
            <h1>Title of My Blog is - {this.props.siteTitle}</h1> 
            </div> 
          ); 
    } 
}   
// define default props for BlogTitle 
BlogTitle.defaultProps = { 
    siteTitle: "React"
} 
  
ReactDOM.render( 
    <BlogTitle />,  
    document.getElementById("root") 
); 
//OUTPUT
Title of My Blog is - React

In the example above, defaultProps named siteTitle is defined for BlogTitle class component (lines: 13-15) and accessed from BlogTitle component using this.props.siteTitle statement (line 7).

Default values for the props can also be defined with JSX syntax using logical OR ( || ) operators as fall back default values (as shown below). If the siteTitle props value is not defined, it will be set by default to 'React'.

//define default prop value 'React' 
<h1>Title of My Blog is - {this.props.siteTitle || 'React'}</h1>

Other methods of setting default props value are discussed in React Guide: default props values & default props.

Further Reading: React Props by default value | Robin Wieruch

Wrapping Up

In this part 2 of the three-part essential prerequisite post series before deep diving into Creating List React component, what are props, how they are used in react components and some use cases were discussed. In Part 3: Learning to Create List React Component, more detail on listing array objects using array.map() method will be discussed.

Acknowledgment: This post was inspired by Robin Wieruch’s How to pass props to components in React and case examples from the GeeksforGeeks articles on ReactJS  on Props Set 1 and set 2.

NEXT POST: Creating List Component in ReactJS

Useful Resources and Links

While preparing this post, I have referred the following references extensively. Please to refer original posts for more detailed information.