Quick intro to React.
By the end of this tutorial, you should be able to:
- Explain what React is and how it compares to Angular and Vue
- Set up a modern React environment with Babel and Webpack
- Create and render a React component in the browser
YOUR TURN: What is React? How does it compare to Angular and Vue?
Create a new project directory:
$ mkdir react-intro
$ cd react-intro
$ npm init -yInstall gulp and babel:
$ npm install --save-dev gulp@4.0.2 gulp-babel@8.0.0 @babel/core@7.21.0 @babel/preset-env@7.20.2YOUR TURN: What's babel? What does
@babel/preset-envdo?
Create a gulpfile.js file in the project root:
const gulp = require('gulp');
const babel = require('gulp-babel');
gulp.task('build', (done) => {
gulp.src(['src/**/*.js'])
.pipe(babel({ presets: ['@babel/preset-env'] }))
.pipe(gulp.dest('lib'));
done();
});Now add a "src" and "lib" folder, and then add an index.js file to the "src" to test babel:
console.log('hello, world!');Finally, add a start script to package.json:
"scripts": {
"start": "gulp build && node lib/index.js"
},Sanity Check:
$ npm start
> react-intro@0.0.0 start /react-intro
> gulp build && node lib/index.js
[18:00:21] Using gulpfile ~/react-intro/gulpfile.js
[18:00:21] Starting 'build'...
[18:00:22] Finished 'build' after 361 ms
hello, world!YOUR TURN: What happened?
Install:
$ npm install --save-dev eslint@8.35.0 eslint-config-airbnb@18.2.1
$ npm install --save-dev eslint-plugin-import@2.27.5 eslint-plugin-jsx-a11y@6.7.1
$ npm install --save-dev eslint-plugin-react@7.32.2 gulp-eslint@6.0.0YOUR TURN: Why lint? What do those packages do?
Add the config to package.json:
"eslintConfig": {
"extends": "airbnb",
"plugins": [
"import"
]
},Update gulpfile.js with a new task:
gulp.task('lint', (done) => {
gulp.src([
'gulpfile.js',
'src/**/*.js',
])
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError());
done();
});Make sure to add the dependency:
const eslint = require('gulp-eslint');Then add the lint task to the build:
gulp.task('build', gulp.series('lint', (done) => {
gulp.src(['src/**/*.js'])
.pipe(babel({ presets: ['@babel/preset-env'] }))
.pipe(gulp.dest('lib'));
done();
}));Run the linter:
$ npm startYou should see a warning:
/react-intro/src/index.js
1:1 warning Unexpected console statement no-console
✖ 1 problem (0 errors, 1 warning)Ignore it.
YOUR TURN: Why are we ignoring it?
Within "src" add a new file called cats.js:
class Cat {
constructor(name) {
this.name = name;
}
meow() {
return `Meow meow, I am ${this.name}`;
}
}
module.exports = Cat;Update index.js:
const Cat = require('./cats');
const toby = new Cat('Toby');
console.log(toby.meow());Run npm start:
Meow meow, I am TobyYOUR TURN: What's happening here?
Install:
$ npm install --save react@18.2.0 react-dom@18.2.0 prop-types@15.8.1YOUR TURN: What's React DOM?
Then add a "dist" folder with an index.html file:
<!doctype html>
<html>
<head>
<title>React Intro</title>
</head>
<body>
<script src="bundle.js"></script>
</body>
</html>YOUR TURN: What's bundle.js?
Add a div to the index.html file, just above the script tag:
<div class="app"></div>Create a new file in "src" called client.jsx:
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import Cat from './cats';
const catMeow = new Cat('Browser Cat').meow();
const App = (props) => {
const { message } = props;
return (
<div>
The cat says:
{ message }
</div>
);
};
App.propTypes = {
message: PropTypes.string.isRequired,
};
ReactDOM.render(<App message={catMeow} />, document.querySelector('.app'));YOUR TURN: Is that HTML in a JS file? Why? What's JSX? Also, what does @babel/preset-react do?
To process the .jsx file, install:
$ npm install --save-dev @babel/preset-react@7.18.6Add the preset to the build task in gulpfile.js:
gulp.task('build', gulp.series('lint', (done) => {
gulp.src(['src/**/*.js'])
.pipe(babel({ presets: ['@babel/preset-env', '@babel/preset-react'] }))
.pipe(gulp.dest('lib'));
done();
}));Finally, update the lint task to handle .jsx files:
gulp.task('lint', (done) => {
gulp.src([
'gulpfile.js',
'src/**/*.js',
'src/**/*.jsx',
])
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError());
done();
});Run the linter:
$ ./node_modules/.bin/gulp lintYou should see the following error:
/react-intro/src/client.jsx
22:44 error 'document' is not defined no-undefYOUR TURN: Why did we get this error?
To correct this, update the eslintConfig in package.json:
"eslintConfig": {
"extends": "airbnb",
"plugins": [
"import"
],
"env": {
"browser": true
}
},Install:
$ npm install --save-dev webpack@5.75.0 webpack-cli@5.0.1 babel-loader@9.1.2 ajv@8.12.0YOUR TURN: What's webpack? What does babel-loader do? Why all these damn tools?!?!
Then add webpack.config.js to the project root:
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/client.jsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
]
},
},
],
},
],
},
resolve: {
extensions: ['*', '.js', '.jsx'],
},
}Update the start script in package.json:
"start": "gulp lint && webpack"Run:
$ npm startThen open the index.html file within "dist" in your browser. You should see:
The cat says: Meow meow, I am Browser Cat