With these slides you will learn how to build your first functional component and how to get started with React using Webpack and Babel. We will also discover the JSX syntax and by the end of the the slides you will be able to render your first site using React components.
2. Hello.
Benny Neugebauer,
Web Team Lead at Wire & Consultant at DCI
https://github.com/bennyn
https://twitter.com/apfelbenny
https://stackoverflow.com/users/451634/
4. A React app written in less than 10 lines of
code...
Hello, World!
Key Players:
1. React
(library for building user interfaces)
2. React DOM
(surface providing DOM access)
3. JSX
(syntax extension to JavaScript)
4. Host element
(<div id=”app”></div>)
import React from 'react';
import ReactDOM from 'react-dom';
const HelloWorld = () => <h1>Hello, World!</h1>;
ReactDOM.render(
<HelloWorld/>,
document.getElementById('app')
);
src/main/index.jsx
5. A painter is only as good as his brush...
Toolchain
1. yarn add react
2. yarn add react-dom
3. yarn add --dev webpack
4. yarn add --dev webpack-cli
5. webpack.config.js
First wave of dependencies:
{
"dependencies": {
"react": "16.4.1",
"react-dom": "16.4.1"
},
"devDependencies": {
"webpack": "4.12.2",
"webpack-cli": "3.0.8"
},
"license": "MIT",
"main": "src/main/index.jsx",
"name": "true-start",
"version": "1.0.0"
}
package.json
6. If you have done everything right, it will fail…
(when running “npx webpack”)
Webpack Config
const pkg = require('./package.json');
module.exports = {
entry: {
[pkg.name]: `${__dirname}/${pkg.main}`,
},
mode: 'development',
output: {
filename: `[name].bundle.js`,
path: `${__dirname}/dist`,
},
resolve: {
extensions: ['.js', '.jsx'],
},
};
webpack.config.js
7. Only the sky is the limit!
Babel
1. yarn add --dev babel-loader
2. yarn add --dev babel-preset-react
3. yarn add --dev babel-core
Second wave of dependencies:
If you are an early bird...
1. yarn add --dev babel-loader@next
2. yarn add --dev @babel/preset-react
3. yarn add --dev @babel/core
8. Chirp, chirp!
const pkg = require('./package.json');
module.exports = {
entry: {
[pkg.name]: `${__dirname}/${pkg.main}`,
},
mode: 'development',
module: {
rules: [
{
test: /.jsx?$/,
exclude: /(bower_components|node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react']
}
}
}
]
},
output: {
filename: `[name].bundle.js`,
path: `${__dirname}/dist`,
},
resolve: {
extensions: ['.js', '.jsx'],
},
};
Babel loader makes use of a Preset that
contains plugins for React & JSX.
The Preset requires a Babel core, because
nothing works without the core.
To make the components play nicely
together, we need to supply a “rules” item for
webpack’s “module” configuration.
Example is based on:
1. babel-loader (8.0.0-beta.4)
2. @babel/preset-react (7.0.0-beta.51)
3. @babel/core (7.0.0-beta.51)
Tip: The “options” can go into a “.babelrc” file.
webpack.config.js
10. React (JS & JSX)
Webpack
babel-loader
@babel/preset-react
@babel/core
JS loaded in HTML
11. Use “webpack-dev-server”, a development
server that provides live reloading.
One more thing...
const pkg = require('./package.json');
const webpack = require('webpack');
module.exports = {
devServer: {
open: true,
port: 8080,
publicPath: '/dist/',
},
[...],
plugins: [
new webpack.HotModuleReplacementPlugin()
],
[...],
};
1. yarn add --dev webpack-dev-server
1. Update webpack.config.js
1. Add “start” script to “package.json” with
command “webpack-dev-server”
Installation:
webpack.config.js
Alternative:
1. Run webpack in watch mode with
“npx webpack -w”
12. Now we are talking! Rewrite of our stateless
functional component (SFC) to a Class
Component.
Create a Component
import React from 'react';
class HelloWorld extends React.Component {
constructor(props) {
super(props);
}
render() {
return <h1>Hello, World!</h1>;
}
}
export default HelloWorld;
import React from 'react';
import ReactDOM from 'react-dom';
import HelloWorld from './HelloWorld';
ReactDOM.render(
<HelloWorld/>,
document.getElementById('app')
);
src/main/index.jsx
src/main/HelloWorld.jsx
13. Rendering dynamic content at ease!
Render Props
import React from 'react';
class HelloWorld extends React.Component {
constructor(props) {
super(props);
}
render() {
return <h1>{this.props.text}</h1>;
}
}
HelloWorld.defaultProps = {
text: 'Placeholder'
};
export default HelloWorld;
import React from 'react';
import ReactDOM from 'react-dom';
import HelloWorld from './HelloWorld';
ReactDOM.render(<HelloWorld
text={Bonjour tout le monde!'}/>,
document.getElementById('app')
);
src/main/index.jsx
src/main/HelloWorld.jsx
14. Props can be used to set the initial state.
Everything further than that should be done
using “setState”.
Changing the state
import React from 'react';
class HelloWorld extends React.Component {
constructor(props) {
super(props);
this.state = {
text: props.text
};
}
appendText(moreText) {
let {text} = this.state;
text = `${text} ${moreText}`;
this.setState({
text
});
}
render() {
return <h1>{this.state.text}</h1>;
}
}
HelloWorld.defaultProps = {
text: 'Placeholder'
};
export default HelloWorld;
import React from 'react';
import ReactDOM from 'react-dom';
import HelloWorld from './HelloWorld';
const component =
ReactDOM.render(<HelloWorld
text={Bonjour tout le monde!'}/>,
document.getElementById('app')
);
component.appendText('Ça va bien?');
src/main/index.jsx
src/main/HelloWorld.jsx
15. We can refactor the previous example into a
component that accepts an array of strings
and outputs a paragraph for each item.
Render many things
import React from 'react';
class HelloWorld extends React.Component {
constructor(props) {
super(props);
this.state = {
texts: props.texts
};
}
render() {
return (
<div>
{
this.state.texts.map((text, index) =>
<p key={index}>{text}</p>)
}
</div>);
}
}
HelloWorld.defaultProps = {
texts: []
};
export default HelloWorld;
import React from 'react';
import ReactDOM from 'react-dom';
import HelloWorld from './HelloWorld';
const texts = [
'Bonjour tout le monde!',
'Ça va bien?'
];
ReactDOM.render(
<HelloWorld texts={texts}/>,
document.getElementById('app')
);
src/main/index.jsx
src/main/HelloWorld.jsx