Component Basics
Types of Components
A component is a function or a class which optionally accepts input, and returns a React element. There are two basic types of components, Functional Components and Class-based components. The difference between the two depends on the state and the usage of the created component. Component States are covered more in depth in the next note, but for now lets see how they're declared.
// Functional component declaration
function NewComponent(props) {
return <div />
}
// Class-based component declaration
class NewComponent extends React.Component {
render() {
return <div />
}
}
In terms of when to use which, in most cases, class-based components are the way to go, but if you have a static component which doesn't and won't ever have any state, or functions attached to it which need to be assessed outside of itself then it's clearer to use a functional component. Essentially, a functional component is sufficient if your class-based component only contains a render method.
Component Class
Every component that we render to the document is part of a component class. As per convention, component classes always start with a capital letter. To create a 'Hello World' component, we'd use the following:
class TestComponentClass extends React.Component {
render() {
return <h1>Hello World!</h1>
}
}
Rendering Components
In order to actually see the 'Hello World' component we previously created, we'd have to use the ReactDOM.render()
function. To render an instance of our component, we call it similarly to an HTML tag, except it's critical to note; components must be self-closing (ex. <TestComp />
).
// ReactDOM.render( component , location );
ReactDOM.render(<TestComponentClass />, document.getElementById("main"))
In the TestComponentClass
declaration, the actual 'Hello World' text is inside a render method. This is because the component class is a set of instructions, and when we call the ReactDOM.render()
function, we are actually we are creating an instance of our class, and following the instructions contained in the class' render method.
Component Logic
React components are quite versatile as well. They allow for the use of variables, multi-line JSX, events, functions, and can even reference themselves. Here is a summarized list:
- Multi-line JSX
class TestComponentClass extends React.Component {
render() {
return (
<div className="wrapper">
<h1 id="title">Title Text</h1>
<p id="content">Content Filler Text</p>
</div>
)
}
}
- Variable Attribution
const user = {
handle: "tester",
bio: "test profile description",
avatar: "img/tester-avatar.png",
}
class TestComponentClass extends React.Component {
render() {
return (
<div className="wrapper">
<h1 id="username">{user.handle}</h1>
<p id="userBio">{user.bio}</p>
<img src={user.avatar} alt="User Photo" />
</div>
)
}
}
- Render Logic
class TestComponentClass extends React.Component {
// Declaration cannot be outside the render function for it to work properly
render() {
// Declaration must be in the render function
const n = Math.floor(Math.random * 10 + 1)
return <h1>The random number is {n}!</h1>
}
}
- this Usage
class TestComponentClass extends React.Component {
// favColour 'getter' method
get favColour() {
return "orange"
}
render() {
return <h1>The favorite colour is {this.favColour}!</h1>
}
}
- this refers to the particular instance of the
TestComponentClass
component. It calls upon the favColour 'getter' method which is why it is referred to asthis.favColour
, notthis.favColour()
. - Event Listeners
class TestComponentClass extends React.Component {
userAlert() {
alert("User prompt!")
}
render() {
return <button onClick={this.userAlert}>Tester Button!</button>
}
}
Crossing Components
Components look like self-closing HTML tags because they can be used as such. They are compatible in JSX which allows you to create components which create instances of other components. Take this for example:
class Navbar extends React.Component {
render {
return (
<nav>
<ul>
<li>Test</li>
<li>Test</li>
<li>Test</li>
</ul>
</nav>
);
}
}
class Header extends React.Component {
render {
return(
<div className="wrapper">
<h1>My Test Page</h1>
<Navbar />
<h3>My Page Head</h3>
</div>
);
}
}
ReactDOM.render(<Header />, document.getElementById('main'));
If we were to render an instance of the Header
component, we would be creating an instance of the Navbar
component as well, and both would show up in the final document render. This can also be done by importing and exporting from different .js
files. If we were to render the same thing, but the Navbar
component was stored elsewhere, it would look like this:
Exporting
import React from 'react';
import ReactDOM from 'react-dom';
export class Navbar extends React.Component {
render {
return (
<nav>
<ul>
<li>Test</li>
<li>Test</li>
<li>Test</li>
</ul>
</nav>
);
}
}
Importing
import React from 'react';
import ReactDOM from 'react-dom';
import {NavItem} from '../nav.js';
class Header extends React.Component {
render {
return(
<div className="wrapper">
<h1>My Test Page</h1>
<Navbar />
<h3>My Page Head</h3>
</div>
);
}
}
ReactDOM.render(<Header />, document.getElementById('main'));