React Components

Posted by kriti-rai on January 26, 2019

React components are like JavaScript functions. They accept arbitrary inputs called props, short for properties, and return something that looks similar to HTML element.

They can be defined in two ways:

1. Using ES6 class

class Person extends React.Component {
 render () {
  return <p>Hi, my name is {this.props.name}.</p>;
 }
}

2. As a function

function Person(props) { 
 return <p>Hi, my name is {this.props.name}.</p>;
} 

Now, we can render an element using Person component as following:

const element = <Person name="Crusoe" />

ReactDOM.render(
 element,
 document.getElementById('root')
);

which renders <p>Hi, my name is Crusoe</p> element.

So, what’s happening here? We passed in a value for the name attribute and Person component assigned it to the name key in the props. So, something like this happened:

props = {
   name : "Crusoe"
}

Similarly, if we were to write:

const element = <Person name="Crusoe" age="32" hometown="Highgate" />

This is what would happen:

props = {
  name : "Crusoe",
  age: 32,
  hometown: "Highgate"
}

Now, let’s modify our Person component so it makes use of those additional attributes, age and hometown just so we can see how user-defined arguments are passed along via props.

class Person extends React.Component {
 render () {
  return (
   <p>
    Hi, my name is {this.props.name}. I am {this.props.age} years old and from  {this.props.hometown}.
   </p>
  )
 }
}

So, now appending our element to the DOM would result in

<p>Hi, my name is Crusoe. I am 32 years old and from Highgate.</p>

We can also call component(s) inside another component. For example, let’s say we have an App component on the top of the view hierarchy of our application as it typically is. We can call Person inside App like this:

class App extends React.Component {
 render () {
  return (
   <div>
      <Person name="Crusoe" age="32" hometown="Highgate"/>
      <Person name="Tom" age="26 hometown="Bronx"/>
      <Person name="Ella" age="25" hometown="Minneapolis"/>
      <Person name="Leia" age="23" hometown="Savannah"/>
    </div>
  )
 }
}

ReactDOM.render(<App />, document.getElementById('root'));
	    

Now, on the page you would see:

Hi, my name is Crusoe. I am 32 years old and from Highgate.

Hi, my name is Tom. I am 26 years old and from Bronx.

Hi, my name is Ella. I am 25 years old and from Minneapolis.

Hi, my name is Leia. I am 23 years old and from Savannah.

Isn’t this cool? Components are reusable and with their ability to take in arguments are dynamic and powerful.

However, (uh oh!) what happens when no argument is provided and/or the property attribute is not defined? Like in the following case:

<Person name="Crusoe" age="32"/>

This would render

<p>Hi, my name is  Crusoe. I am 32 years old and from .

And, we don’t want that. We want to be prepared for scenarious when data is missing or undefined.

Enter default props!!!

We add defaultProps property to the component so that whenever the value of a prop is missing or undefined, the component uses the default value provided in defaultProps instead. For example, to fix the issue above we can do this:

Person.defaultProps = {
  hometown: 'XYZ'
}

This would result in

<p>Hi, my name is  Crusoe. I am 32 years old and from XYZ. 

Conclusion

React components are basically JavaScript functions and can also be defined using ES6 class. They contain:

  • props, short for properties
  • data
  • state (not discussed here)
  • markup (delivered by render())

Components are powerful and dynamic given their reusability and their ability to take in user-defined arguments. However, in case an argument is missing or not defined, the resulting element might look funky. In order to prevent such scenarios, it’s a good practice to definedefaultProps, setting default value(s) for the component’s prop(s).