React/ReactJS: Components and Props
The line below exist inside the src/index.js
file of the boilerplate application created by the create-react-app
command line (CL) tool.
ReactDOM.render(<App/>, document.getElementById('root'));
The first argument <App/>
passed into the ReactDOM.render()
function is a component. They are the fundamental independent blocks of code of a ReactJS application and we are going to learn about them here.
Note that ReactJS components should always start with a capital letter. Components starting with lowercase letters are treated like any other HTML DOM tags.
We begin by replacing the <App/>
component directly with a simple JSX <h1>Hello, World!</h1>
.
ReactDOM.render(<h1>Hello, World!</h1>, document.getElementById('root'));
What happens from here, we have described in our previous tutorial "The JSX". The Babel package transforms this JSX into React.createElement()
function calls as follows —
React.createElement(
"h1",
null,
"Hello, World!"
);
Note that I wrote "function calls" in plural to imply generically that if h1
has a child element, another React.createElement()
would appear nested. You can try out your JSXes in Babel's online compiler here and see how they are converted.
The React.createElement()
function in turn creates an object — a JavaScript object — known as React Element. We can check what this object is like by doing console.log()
of what the Babel compiler returned.
console.log(React.createElement("h1", null, "Hello, World!"));
{
key: null,
props: {
children: "Hello, World!"
},
ref: null,
type: "h1"
}
Observe that the created object, a React element, possesses the following properties — key
, props
, ref
, type
; but we will not delve into any of it right now.
ReactDOM.render()
then renders this object into the div
element with id="root"
inside public/index.html
.
Functional Components
Let us define a simple JavaScript function called Hello()
which returns the above <h1>Hello, World!</h1>
JSX code. To pass this JSX into ReactDOM.render()
we need to pass our Hello()
function as <Hello/>
into ReactDOM.render()
. This has the same effect as above where the JSX is passed directly into ReactDOM.render()
and gets rendered in the browser.
function Hello() {
return <h1>Hello, World!</h1>;
}
ReactDOM.render(<Hello/>, document.getElementById('root'));
We can rewrite our Hello()
function using the recent ES6 arrow function expression (=>
token) as shown below.
const Hello = () => {
return (
<h1>Hello, World!</h1>
);
}
ReactDOM.render(<Hello/>, document.getElementById('root'));
Components as such which are pure JavaScript functions are known as Functional Components.
Class Components
We can define components as ES6 classes too. For example, the above Hello()
function can also be defined as a subclass of React.Component
as shown below.
class Hello extends React.Component {
render() {
return <h1>Hello, World!</h1>;
}
}
ReactDOM.render(<Hello/>, document.getElementById('root'));
The render()
method is the only necessary method for a subclass of React.Component
to define inside it. There can be many other methods besides render()
, but they are all optional. Components which are defined as ES6 classes are known as Class Components.
Props
Now since Hello()
is a function, we can pass arguments to it. We modify it a little to pass one argument to it — an object called props
("props" means properties). Our props object has a property called name
. The name
property is passed as an attribute with the value "Agnes".
function Hello(props) {
return <h1>Hello, {props.name}!</h1>;
}
ReactDOM.render(<Hello name="Agnes"/>, document.getElementById('root'));
Props can be a string, an integer, an array, an object or even a function.
The class version of the above component with props is as below.
class Hello extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
ReactDOM.render(<Hello name="Agnes"/>, document.getElementById('root'));
defaultProps
We need not always pass props to a component as an attribute-value pair. There is a function called defaultProps()
which allows us to "bypass" it.
class Hello extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
Hello.defaultProps = {
name: 'Agnes'
};
ReactDOM.render(<Hello/>, document.getElementById('root'));
Difference between Functional Components and Class Components
Both functional components and class components have props
, an immutable object which comes from parent components. But there is one fundamental difference between them: class components have an additional object know as state, which has its scope limited only to the current component. We will learn more about them in detail here.