React Components

A fundamental part of any React application is the way the page is orchestrated using a collection of components. Getting components right is a vital part of any successful React project.

The first thing to understand about a React component is that it is not the same as an HTML element despite the syntax looking incredibly similar in some instances. A <div> in JSX is not the same thing as a <div> in HTML.

Components in JSX are functionally Javascript clojures under the surface. This means that Javascript needs to count references to each of them, and to keep an area of memory allocated to it, and consequently garbage to be collected if they're ever unallocated and removed from the page. React needs to keep a unique reference to each one. Where an application in Vue appears to be HTML with Javascript decoration, and in Angular things are HTML templates populated by Javascript, in React there effectively is no user-creaetd HTML. There is only JSX and Javascript. What gets displayed on the page is abstract code generated by the React app. You are not writing HTML.

What this means in practise is really that you should think of React component as mini applications that output code rather than elements on the page.

To look at different ways of creating components and what we can do with them we need to start with the sort of basic React app container component that create-react-app might give us to start.

import React from 'react';

class App extends React.Component {
  render() {
    return (
      <div className="App">
		This is the app container.
      </div>
    );
  }
}

This app is a component in itself. The div JSX renders an HTML div tag with a class of App and some text content. It's very basic, but it's only a demo. We want to populate it with a component of our own.

There are two main ways to create a React component. They're effectively interchangable, but it's quite useful to think of them as separate as it makes it more obvious what each component is for.

The first method is an anonymous function. It looks like this;

import React from react;

export default function(){
	return (<h1 className='MyComponent'>My title, in JSX</h1>);
}

The alternative is to extend the React component class;

import React from react;

class MyComponent extends React.Component {
	render(){
		return (<h1 className='MyComponent'>My title, in JSX</h1>);
	}
}

In both cases the React library needs to be imported in to the current scope in order for JSX to work. In the first example however that's literally all that's necessary.

To display either of the components we can simply import them in to our React app and use the component's JSX. It'll be replaced by the rendered HTML.

import React from 'react';
import MyComponent from './MyComponent.js';

class App extends React.Component {
  render() {
    return (
      <div className="App">
        <MyComponent />
      </div>
    );
  }
}

What's changed is the addition of an import to bring the new component in to the application, and a JSX <MyComponent /> self-closing element to render the output of the component's render function.

There isn't much more to say about the anonymous component function. If all you need is to render some HTML then this way of creating a component is ideal. Its advantage is its simplicity.

The second way relies on extending the React component base class, which is a little more complicated, but affords the component a wealth of additional features such as lifetime callbacks, an optional constructor method, a way of managing the component's state, and more.

If we need to manage state in a component then we need to add a constructor and initialise a state object.

import React from react;

class MyComponent extends React.Component {
	constructor(){
		this.state = {
			name: 'Ooer'
		}
	}
	render(){
		return (<h1 className='MyComponent'>My title, in JSX</h1>);
	}
}

Now when the component is initialised a state object will be created with a name property that we can access in the component's render method using this.state.name.

import React from react;

class MyComponent extends React.Component {
	constructor(){
		this.state = {
			name: 'Ooer'
		}
	}
	render(){
		return (<h1 className='MyComponent'>My title, {this.state.name}, in JSX</h1>);
	}
}

React's components are incredibly powerful. There are a lot more features that aren't covered here; we'll explore them in a later post.