Vanilla React

We will start learning React by using React with vanilla JS - which means we will not include any tooling first, and only code with a simple HTML file and a script tag.

html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="https://codepen.io/malcolmkee/pen/xmvMNY.css" />
<title>React Movie App</title>
</head>
<body>
<div id="root">not rendered</div>
<script src="https://unpkg.com/react@16.7.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0/umd/react-dom.development.js"></script>
<script>
// Your code goes here
</script>
</body>
</html>
html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="https://codepen.io/malcolmkee/pen/xmvMNY.css" />
<title>React Movie App</title>
</head>
<body>
<div id="root">not rendered</div>
<script src="https://unpkg.com/react@16.7.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0/umd/react-dom.development.js"></script>
<script>
// Your code goes here
</script>
</body>
</html>
  • the codepen link is the css that I’ve created for this workshop to make the code-along app looks nicer. We’re not going to discuss about css in this workshop.
  • unpkg is a CDN for npm, which allows us to explore npm package easily. (If you not sure what is npm, relax. We’ll talk about it slightly later.) The two unpkg script tag is used to load the two packages we need to develop in ReactJS:
    • React: this is the library to construct React component, which I will introduce you right after this. It contains no way to render the component, it’s just the declaration of the component.
    • ReactDOM: the rendering layer. Since we’re learning about rendering in browser today, we’ll be using ReactDOM. There are other rendering layer e.g. React Native, React 360 etc. Both React and ReactDOM are required, but the their orders do not matter.
  • the last script tag would be where we write our code. It must be after the two unpkg script tags.

In the <script> tag, add the following code

javascript
const App = function () {
return React.createElement('div', {}, React.createElement('h1', {}, 'React Movie App'));
};
ReactDOM.render(React.createElement(App), document.getElementById('root'));
javascript
const App = function () {
return React.createElement('div', {}, React.createElement('h1', {}, 'React Movie App'));
};
ReactDOM.render(React.createElement(App), document.getElementById('root'));
  • We create a component, call it as App. React is all about creating component, and a component can be as simple as a function.
  • There are two types of component - function component & class component. This is a function component.
  • A component must return markup, which is generated by React.createElement.
  • React.createElement is a function that takes three parameters: component type, properties, and children. For HTML element and web component, the component type would be a string.
  • ReactDOM.render is used to render our App component to the HTML. In this case, a div with id root.
  • Notice we’re using React.createElement with App as a parameter to ReactDOM.render. We need an instance of App to render out. App is a class of components and we need to render one instance of App. That’s what React.createElement does: it makes an instance of a component.
  • A React component is not a markup itself; it is a markup generator.

Exercise

  1. Create a file and name it as index.html.
  2. Add the code above in the file.

Modify your code, so that it becomes

javascript
const Movie = () =>
React.createElement('div', { className: 'movie-container' }, [
React.createElement('h1', {}, 'Aquaman'),
React.createElement('h2', {}, '2018-12-07'),
]);
const App = function () {
return React.createElement('div', {}, [
React.createElement(
'div',
{ className: 'title-bar' },
React.createElement('h1', {}, 'React Movie App')
),
React.createElement(Movie),
React.createElement(Movie),
React.createElement(Movie),
]);
};
ReactDOM.render(React.createElement(App), document.getElementById('root'));
javascript
const Movie = () =>
React.createElement('div', { className: 'movie-container' }, [
React.createElement('h1', {}, 'Aquaman'),
React.createElement('h2', {}, '2018-12-07'),
]);
const App = function () {
return React.createElement('div', {}, [
React.createElement(
'div',
{ className: 'title-bar' },
React.createElement('h1', {}, 'React Movie App')
),
React.createElement(Movie),
React.createElement(Movie),
React.createElement(Movie),
]);
};
ReactDOM.render(React.createElement(App), document.getElementById('root'));
  • to make an element to have multiple children, just pass it an array of elements.
  • Movie is our second component. I use arrow function syntax here, which will have an implicit return if the function body is a single expression
  • We can have multiple Movie instances by calling React.createElement multiple times!
  • className props will be translated to class properties in HTML. This is one of the few instances where React properties and HTML properties are not the same to avoid complication due to reserved JS keywords (class is used to declare class in JS), the others are htmlFor, tabIndex etc.
  • If you’re seeing console warning about keys, ignore it for now.

We have multiple movies but it’s not very useful component yet, since not all movies has name Aquaman. Let’s make Movie component a bit more useful.

javascript
const Movie = (props) =>
React.createElement('div', { className: 'movie-container' }, [
React.createElement('h1', {}, props.name),
React.createElement('h2', {}, props.releaseDate),
]);
const App = function () {
return React.createElement('div', {}, [
React.createElement(
'div',
{ className: 'title-bar' },
React.createElement('h1', {}, 'React Movie App')
),
React.createElement(Movie, {
name: 'Aquaman',
releaseDate: '2018-12-07',
}),
React.createElement(Movie, {
name: 'Bumblebee',
releaseDate: '2018-12-15',
}),
React.createElement(Movie, {
name: 'Fantastic Beasts: The Crimes of Grindelwald',
releaseDate: '2018-11-14',
}),
]);
};
ReactDOM.render(React.createElement(App), document.getElementById('root'));
javascript
const Movie = (props) =>
React.createElement('div', { className: 'movie-container' }, [
React.createElement('h1', {}, props.name),
React.createElement('h2', {}, props.releaseDate),
]);
const App = function () {
return React.createElement('div', {}, [
React.createElement(
'div',
{ className: 'title-bar' },
React.createElement('h1', {}, 'React Movie App')
),
React.createElement(Movie, {
name: 'Aquaman',
releaseDate: '2018-12-07',
}),
React.createElement(Movie, {
name: 'Bumblebee',
releaseDate: '2018-12-15',
}),
React.createElement(Movie, {
name: 'Fantastic Beasts: The Crimes of Grindelwald',
releaseDate: '2018-11-14',
}),
]);
};
ReactDOM.render(React.createElement(App), document.getElementById('root'));
  • Now Movie is a more flexible component that accepts props from its parent.
  • props (stands for properties) are variables that parent component (App) pass to its children (Movie).
  • All React component accepts props as input, and produces the markup (result of React.createElement) as its output.

As mentioned before, there are 2 types of component - function component and class component. Let’s convert App to class component.

javascript
class App extends React.Component {
render() {
return React.createElement('div', {}, [
React.createElement(
'div',
{ className: 'title-bar' },
React.createElement('h1', {}, 'React Movie App')
),
React.createElement(Movie, {
name: 'Aquaman',
releaseDate: '2018-12-07',
}),
React.createElement(Movie, {
name: 'Bumblebee',
releaseDate: '2018-12-15',
}),
React.createElement(Movie, {
name: 'Fantastic Beasts: The Crimes of Grindelwald',
releaseDate: '2018-11-14',
}),
]);
}
}
javascript
class App extends React.Component {
render() {
return React.createElement('div', {}, [
React.createElement(
'div',
{ className: 'title-bar' },
React.createElement('h1', {}, 'React Movie App')
),
React.createElement(Movie, {
name: 'Aquaman',
releaseDate: '2018-12-07',
}),
React.createElement(Movie, {
name: 'Bumblebee',
releaseDate: '2018-12-15',
}),
React.createElement(Movie, {
name: 'Fantastic Beasts: The Crimes of Grindelwald',
releaseDate: '2018-11-14',
}),
]);
}
}
  • App is functionally same as before. However, a class component unlocks more powers, like having state and defining lifecycle methods, which will be explained later.
  • Each class component must have a render method, which must return the result of React.createElement call.
  • For function component, props are available as first parameter of the function. For class component, props are available via this.props.
  • Both function component and render method of class component must be pure function, i.e.:
    • given the same input, it always return the same output (markup)
    • it does not have any side effect - you should not make ajax call / add event listener here.
  • So, when you should make an ajax call in a React app? That will be answered in part 3 of this course. But before that, let’s dive into the tooling around React.

Exercise

  1. Add Movie component in your code and use it as explained above.
  2. Modify your App component to a class component
  3. (Bonus) Add a new props genres in your Movie component and render it in a span tag.