React JS
React JS
About
This book is a compilation of notes and professional tips for developers working with React JS. It is
created for educational purposes to help programmers learn and master React.
The information presented in this book is not guaranteed to be correct nor accurate; use at your own
risk.
Contents
● About
● Chapter 1: Getting started with React
○ Section 1.1: What is ReactJS?
○ Section 1.2: Installation or Setup
○ Section 1.3: Hello World with Stateless Functions
○ Section 1.4: Absolute Basics of Creating Reusable Components
○ Section 1.5: Create React App
○ Section 1.6: Hello World
○ Section 1.7: Hello World Component
● Chapter 2: Components
○ Section 2.1: Creating Components
○ Section 2.2: Basic Component
○ Section 2.3: Nesting Components
○ Section 2.4: Props
○ Section 2.5: Component states - Dynamic user-interface
○ Section 2.6: Variations of Stateless Functional Components
○ Section 2.7: setState pitfalls
● Chapter 3: Using ReactJS with TypeScript
○ Section 3.1: ReactJS component written in TypeScript
○ Section 3.2: Installation and Setup
○ Section 3.3: Stateless React Components in TypeScript
○ Section 3.4: Stateless and property-less Components
● Chapter 4: State in React
○ Section 4.1: Basic State
○ Section 4.2: Common Antipattern
○ Section 4.3: setState()
○ Section 4.4: State, Events And Managed Controls
● Chapter 5: Props in React
○ Section 5.1: Introduction
○ Section 5.2: Default props
○ Section 5.3: PropTypes
○ Section 5.4: Passing down props using spread operator
○ Section 5.5: Props.children and component composition
○ Section 5.6: Detecting the type of Children components
● Chapter 6: React Component Lifecycle
○ Section 6.1: Component Creation
○ Section 6.2: Component Removal
○ Section 6.3: Component Update
○ Section 6.4: Lifecycle method call in different states
○ Section 6.5: React Component Container
● Chapter 7: Forms and User Input
○ Section 7.1: Controlled Components
○ Section 7.2: Uncontrolled Components
● Chapter 8: React Boilerplate [React + Babel + Webpack]
○ Section 8.1: react-starter project
○ Section 8.2: Setting up the project
● Chapter 9: Using ReactJS with jQuery
○ Section 9.1: ReactJS with jQuery
● Chapter 10: React Routing
○ Section 10.1: Example Routes.js file, followed by use of Router Link in
component
○ Section 10.2: React Routing Async
● Chapter 11: Communicate Between Components
○ Section 11.1: Communication between Stateless Functional Components
● Chapter 12: How to setup a basic webpack, react and babel environment
○ Section 12.1: How to build a pipeline for a customized "Hello world" with
images
● Chapter 13: React.createClass vs extends React.Component
○ Section 13.1: Create React Component
○ Section 13.2: "this" Context
○ Section 13.3: Declare Default Props and PropTypes
○ Section 13.4: Mixins
○ Section 13.5: Set Initial State
○ Section 13.6: ES6/React this keyword with ajax to get data from server
● Chapter 14: React AJAX call
○ Section 14.1: HTTP GET request
○ Section 14.2: HTTP GET request and looping through data
○ Section 14.3: Ajax in React without a third party library - a.k.a with VanillaJS
● Chapter 15: Communication Between Components
○ Section 15.1: Child to Parent Components
○ Section 15.2: Not-related Components
○ Section 15.3: Parent to Child Components
● Chapter 16: Stateless Functional Components
○ Section 16.1: Stateless Functional Component
● Chapter 17: Performance
○ Section 17.1: Performance measurement with ReactJS
○ Section 17.2: React's diff algorithm
○ Section 17.3: The Basics - HTML DOM vs Virtual DOM
○ Section 17.4: Tips & Tricks
● Chapter 18: Introduction to Server-Side Rendering
○ Section 18.1: Rendering components
● Chapter 19: Setting Up React Environment
○ Section 19.1: Simple React Component
○ Section 19.2: Install all dependencies
○ Section 19.3: Configure webpack
○ Section 19.4: Configure babel
○ Section 19.5: HTML file to use react component
○ Section 19.6: Transpile and bundle your component
● Chapter 20: Using React with Flow
○ Section 20.1: Using Flow to check prop types of stateless functional
components
○ Section 20.2: Using Flow to check prop types
● Chapter 21: JSX
○ Section 21.1: Props in JSX
○ Section 21.2: Children in JSX
● Chapter 22: React Forms
○ Section 22.1: Controlled Components
● Chapter 23: User interface solutions
○ Section 23.1: Basic Pane
○ Section 23.2: Panel
○ Section 23.3: Tab
○ Section 23.4: PanelGroup
○ Section 23.5: Example view with PanelGroups
● Chapter 24: Using ReactJS in Flux way
○ Section 24.1: Data Flow
● Chapter 25: React, Webpack & TypeScript installation
○ Section 25.1: webpack.config.js
○ Section 25.2: tsconfig.json
○ Section 25.3: My First Component
● Chapter 26: How and why to use keys in React
○ Section 26.1: Basic Example
● Chapter 27: Keys in react
○ Section 27.1: Using the id of an element
○ Section 27.2: Using the array index
● Chapter 28: Higher Order Components
○ Section 28.1: Higher Order Component that checks for authentication
○ Section 28.2: Simple Higher Order Component
● Chapter 29: React with Redux
○ Section 29.1: Using Connect
● Chapter 30: Integrating React with a Spring Boot Backend
○ Section 30.1: Introduction and Strategy
○ Section 30.2: Prerequisites
○ Section 30.3: Step 1 - Creating the Spring Boot Project
○ Section 30.4: Step 2 - Building a Simple REST Controller
○ Section 30.5: Step 3 - Running and Testing the Backend
○ Section 30.6: Step 4 - Setting up the React Application
○ Section 30.7: Step 5 - Creating the React Component to Fetch Data
○ Section 30.8: Step 6 - Configuring the Development Proxy
○ Section 30.9: Step 7 - Running the Full Application in Development
○ Section 30.10: Step 8 - Configuring for a Production Build
● Chapter 31: Deploying the Integrated Application
○ Section 31.1: Deployment Strategies Overview
○ Section 31.2: Strategy 1 - Direct Deployment to a VPS
○ Section 31.3: Strategy 2 - Containerization with Docker
○ Section 31.4: Strategy 3 - Deployment to a Cloud Platform (Heroku)
Chapter 1: Getting started with React
Version Release Date Table
This table shows the release history of React.
Version Release
Date
0.3.0 2013-05-29
0.4.0 2013-07-17
0.5.0 2013-10-16
0.8.0 2013-12-19
0.9.0 2014-02-20
0.10.0 2014-03-21
0.11.0 2014-07-17
0.12.0 2014-10-28
0.13.0 2015-03-10
0.14.0 2015-10-07
15.0.0 2016-04-07
15.1.0 2016-05-20
15.2.0 2016-07-01
15.2.1 2016-07-08
15.3.0 2016-07-29
15.3.1 2016-08-19
15.3.2 2016-09-19
15.4.0 2016-11-16
15.4.1 2016-11-23
15.4.2 2017-01-06
15.5.0 2017-04-07
15.6.0 2017-06-13
15.6.1 2017-06-14
15.6.2 2017-09-25
16.0.0 2017-09-26
16.1.0 2017-11-09
16.1.1 2017-11-13
16.3.0 2018-03-29
16.3.1 2018-04-03
16.3.2 2018-04-16
ReactJS uses virtual DOM based mechanism to fill in data (views) in HTML DOM. The virtual DOM
works fast owning to the fact that it only changes individual DOM elements instead of reloading
complete DOM every time.
A React application is made up of multiple components, each responsible for outputting a small,
reusable piece of HTML. Components can be nested within other components to allow complex
applications to be built out of simple building blocks. A component may also maintain internal state -
for example, a TabList component may store a variable corresponding to the currently open tab.
React allows us to write components using a domain-specific language called JSX. JSX allows us to
write our components using HTML, whilst mixing in JavaScript events. React will internally convert
this into a virtual DOM, and will ultimately output our HTML for us.
React "reacts" to state changes in your components quickly and automatically to rerender the
components in the HTML DOM by utilizing the virtual DOM. The virtual DOM is an in-memory
representation of an actual DOM. By doing most of the processing inside the virtual DOM rather than
directly in the browser's DOM, React can act quickly and only add, update, and remove components
which have changed since the last render cycle occurred.
Basic Inclusion
Generated html
<!DOCTYPE html>
<html>
<head></head>
<body>
<script type="text/javascript" src="/path/to/react.js"></script>
<script type="text/javascript" src="/path/to/react-dom.js"></script>
<script type="text/javascript">
// Use react JavaScript code here or in a separate file
</script>
</body>
</html>
To get the JavaScript files, go to the installation page of the official React documentation.
React also supports JSX syntax. JSX is an extension created by Facebook that adds XML syntax to
JavaScript. In order to use JSX you need to include the Babel library and change <script
type="text/javascript"> to <script type="text/babel"> in order to translate JSX to
Javascript code.
Generated html
<!DOCTYPE html>
<html>
<head></head>
<body>
<script type="text/javascript" src="/path/to/react.js"></script>
<script type="text/javascript" src="/path/to/react-dom.js"></script>
<script src="https://npmcdn.com/[email protected]/browser.min.js"></script>
<script type="text/babel">
// Use react JSX code here or in a separate file
</script>
</body>
</html>
You can also install React using npm by doing the following:
Generated bash
Generated javascript
Facebook released its own package manager named Yarn, which can also be used to install React.
After installing Yarn you just need to run this command:
Generated bash
For example:
Generated javascript
let a = 0;
const statefulSum = () => a++;
As you can see from the above example that, statelessSum is always will return the same values
given a and b. However, statefulSum function will not return the same values given even no
parameters. This type of function's behaviour is also called as a side-effect. Since, the component
affects somethings beyond.
So, it is advised to use stateless components more often, since they are side-effect free and will
create the same behaviour always. That is what you want to be after in your apps because
fluctuating state is the worst case scenario for a maintainable program.
The most basic type of react component is one without state. React components that are pure
functions of their props and do not require any internal state management can be written as simple
JavaScript functions. These are said to be Stateless Functional Components because they are a
function only of props, without having any state to keep track of.
Generated html
// In HTML
<div id="element"></div>
Generated javascript
// In React
const MyComponent = props => {
return <h1>Hello, {props.name}!</h1>;
};
Note that all that this component does is render an h1 element containing the name prop. This
component doesn't keep track of any state. Here's an ES6 example as well:
Generated javascript
HelloWorld.propTypes = {
name: React.PropTypes.string.isRequired
}
Since these components do not require a backing instance to manage the state, React has more
room for optimizations. The implementation is clean, but as of yet no such optimizations for stateless
components have been implemented.
As React concerns itself only with an application's view, the bulk of development in React will be the
creation of components. A component represents a portion of the view of your application. "Props"
are simply the attributes used on a JSX node (e.g. <SomeComponent someProp="some prop's
value" />), and are the primary way our application interacts with our components. In the snippet
above, inside of SomeComponent, we would have access to this.props, whose value would be the
object {someProp: "some prop's value"}.
It can be useful to think of React components as simple functions - they take input in the form of
"props", and produce output as markup. Many simple components take this a step further, making
themselves "Pure Functions", meaning they do not issue side effects, and are idempotent (given a
set of inputs, the component will always produce the same output). This goal can be formally
enforced by actually creating components as functions, rather than "classes". There are three ways
of creating a React component:
);
React.createClass()
Generated javascript
});
ES2015 Classes
Generated javascript
Generated javascript
Functional components cannot have "state" within them. So if your component needs to have a
state, then go for class based components. Refer Creating Components for more information.
As a final note, react props are immutable once they have been passed in, meaning they cannot be
modified from within a component. If the parent of a component changes the value of a prop, React
handles replacing the old props with the new, the component will rerender itself using the new
values.
Installation
Generated bash
Generated bash
create-react-app my-app
Navigate to the newly created directory and run the start script.
Generated bash
cd my-app/
npm start
Configuration
Generated bash
This allows editing of all configuration files. N.B. this is an irreversible process.
Alternatives
● enclave
● nwb
● motion
● rackt-cli
● budō
● rwb
● quik
● sagui
● roc
Generated bash
Here's a basic example that uses React's main API to create a React element and the React DOM
API to render the React element in the browser.
Generated html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<!-- Include the React and ReactDOM libraries -->
<script src="https://fb.me/react-15.2.1.js"></script>
<script src="https://fb.me/react-dom-15.2.1.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/javascript">
// create a React element rElement
var rElement = React.createElement('h1', null, 'Hello, world!');
With JSX
Instead of creating a React element from strings one can use JSX (a Javascript extension created
by Facebook for adding XML syntax to JavaScript), which allows to write:
Generated javascript
as the equivalent (and easier to read for someone familiar with HTML):
Generated javascript
The code containing JSX needs to be enclosed in a <script type="text/babel"> tag. Everything
within this tag will be transformed to plain Javascript using the Babel library (that needs to be
included in addition to the React libraries).
Generated html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<!-- Include the React and ReactDOM libraries -->
<script src="https://fb.me/react-15.2.1.js"></script>
<script src="https://fb.me/react-dom-15.2.1.js"></script>
<!-- Include the Babel library -->
<script src="https://npmcdn.com/[email protected]/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
// create a React element rElement using JSX
var rElement = <h1>Hello, world!</h1>;
Generated javascript
A Component can also receive props. These are properties passed by its parent in order to specify
some values the component cannot know by itself; a property can also contain a function that can be
called by the component after certain events occur - for example, a button could receive a function
for its onClick property and call it whenever it is clicked. When writing a component, its props can
be accessed through the props object on the Component itself:
Generated javascript
The example above shows how the component can render an arbitrary string passed into the name
prop by its parent. Note that a component cannot modify the props it receives.
A component can be rendered within any other component, or directly into the DOM if it's the
topmost component, using ReactDOM.render and providing it with both the component and the
DOM Node where you want the React tree to be rendered:
Generated javascript
By now you know how to make a basic component and accept props. Lets take this a step further
and introduce state.
For demo sake, let's make our Hello World app, display only the first name if a full name is given.
Generated javascript
render() {
return <h1>Hello, {this.state.name}!</h1>
}
}
Note: Each component can have it's own state or accept it's parent's state as a prop.
Chapter 2: Components
Section 2.1: Creating Components
This is an extension of Basic Example:
Basic Structure
Generated javascript
render(
<FirstComponent name={ 'User' } />,
document.getElementById('content')
);
The above example is called a stateless component as it does not contain state (in the React sense
of the word).
In such a case, some people find it preferable to use Stateless Functional Components, which are
based on ES6 arrow functions.
In many applications there are smart components that hold state but render dumb components that
simply receive props and return HTML as JSX. Stateless functional components are much more
reusable and have a positive performance impact on your application.
1. When rendered they receive an object with all the props that were passed down
2. They must return the JSX to be rendered
Generated javascript
Stateful Components
In contrast to the 'stateless' components shown above, 'stateful' components have a state object that
can be updated with the setState method. The state must be initialized in the constructor before it
can be set:
Generated javascript
this.state = {
toggle: true
};
onClick() {
this.setState((prevState, props) => ({
toggle: !prevState.toggle
}));
}
render() {
return (
<div onClick={this.onClick}>
Hello, {this.props.name}! I am a SecondComponent.
<br />
Toggle is: {this.state.toggle}
</div>
);
}
}
Extending a component with PureComponent instead of Component will automatically implement the
shouldComponentUpdate() lifecycle method with shallow prop and state comparison. This keeps
your application more performant by reducing the amount of un-necessary renders that occur. This
assumes your components are 'Pure' and always render the same output with the same state and
props input.
Generated javascript
Higher order components are used when you want to share logic across several components
regardless of how different they render.
index.html
Generated html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>React Tutorial</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
</head>
<body>
<div id="content"></div>
<script type="text/babel" src="scripts/example.js"></script>
</body>
</html>
You can create a basic component using the following code in a separate file:
scripts/example.js
Generated javascript
ReactDOM.render(
<FirstComponent />, // Note that this is the same as the variable you stored above
document.getElementById('content')
);
You will get the following result (note what is inside of div#content):
Generated html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>React Tutorial</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
</head>
<body>
<div id="content">
<div className="firstComponent">
Hello, world! I am a FirstComponent.
</div>
</div>
<script type="text/babel" src="scripts/example.js"></script>
</body>
</html>
Generated javascript
You can nest and refer to those components in the definition of a different component:
Generated javascript
Further nesting can be done in three ways, which all have their own places to be used.
Pros
Cons
Good if
Generated javascript
This is the style where A composes B and A tells B to compose C. More power to parent
components.
Pros
Cons
Good if
● B should accept to compose something different than C in the future or somewhere else
● A should control the lifecycle of C
B would render C using this.props.children, and there isn't a structured way for B to know what
those children are for. So, B may enrich the child components by giving additional props down, but if
B needs to know exactly what they are, #3 might be a better option.
Generated javascript
This is the style where A composes B and B provides an option for A to pass something to compose
for a specific purpose. More structured composition.
Pros
● Composition as a feature
● Easy validation
● Better composability
Cons
Good if
#3 is usually a must for making a public library of components but also a good practice in general to
make composable components and clearly define the composition features. #1 is the easiest and
fastest to make something that works, but #2 and #3 should provide certain benefits in various use
cases.
Generated jsx
Inside the definition for MyComponent userID will now be accessible from the props object:
Generated javascript
It's important to define all props, their types, and where applicable, their default value:
Generated javascript
MyComponent.defaultProps = {
someObject: {},
title: 'My Default Title'
}
In this example the prop someObject is optional, but the prop userID is required. If you fail to
provide userID to MyComponent, at runtime the React engine will show a console warning you that
the required prop was not provided. Beware though, this warning is only shown in the development
version of the React library, the production version will not log any warnings.
Generated javascript
Generated javascript
console.log(this.props.title);
It's also a safeguard for use of object array and functions. If you do not provide a default prop for an
object, the following will throw an error if the prop is not passed:
Generated javascript
if (this.props.someObject.someKey)
In example above, this.props.someObject is undefined and therefore the check of someKey will
throw an error and the code will break. With the use of defaultProps you can safely use the above
check.
Generated javascript
// I have used ReactBootstrap elements. But the code works with regular html elements also
var Button = ReactBootstrap.Button;
var Form = ReactBootstrap.Form;
var FormGroup = ReactBootstrap.FormGroup;
var FormControl = ReactBootstrap.FormControl;
handleTitleSubmit: function() {
//code to handle input box submit - for example, issue an ajax request to change name in database
},
handleTitleChange: function(e) {
//code to change the name in form input box. newTitle is initialized as empty string. We need to
//update it with the string currently entered by user in the form
this.setState({newTitle: e.target.value});
},
changeComponent: function() {
// this toggles the show variable which is used for dynamic UI
this.setState({show: !this.state.show});
},
render: function() {
var clickableTitle;
if(this.state.show) {
clickableTitle = <Form inline onSubmit={this.handleTitleSubmit}>
<FormGroup controlId="formInlineTitle">
<FormControl type="text" onChange={this.handleTitleChange} />
</FormGroup>
</Form>;
} else {
clickableTitle = <div>
<Button bsStyle="link" onClick={this.changeComponent}>
<h3> Default Text </h3>
</Button>
</div>;
}
return (
<div className="comment">
{clickableTitle}
</div>
);
}
});
ReactDOM.render(
<Comment />, document.getElementById('content')
);
The main part of the code is the clickableTitle variable. Based on the state variable show, it can
be either be a Form element or a Button element. React allows nesting of components.
So we can add a {clickableTitle} element in the render function. It looks for the
clickableTitle variable. Based on the value this.state.show, it displays the corresponding
element.
Section 2.6: Variations of Stateless Functional Components
Generated javascript
const languages = [
'JavaScript',
'Python',
'Java',
'Elm',
'TypeScript',
'C#',
'F#'
]
// one liner
const Language = ({language}) => <li>{language}</li>
Language.propTypes = {
message: React.PropTypes.string.isRequired
}
/**
* If there are more than one line.
* Please notice that round brackets are optional here,
* However it's better to use them for readability
*/
const LanguagesList = ({languages}) => {
<ul>
{languages.map(language => <Language language={language} />)}
</ul>
}
LanguagesList.propTypes = {
languages: React.PropTypes.array.isRequired
}
/**
* This syntax is used if there are more work beside just JSX presentation
* For instance some data manipulations needs to be done.
* Please notice that round brackets after return are required,
* Otherwise return will return nothing (undefined)
*/
const LanguageSection = ({header, languages}) => {
// do some work
const formattedLanguages = languages.map(language => language.toUpperCase())
return (
<fieldset>
<legend>{header}</legend>
<LanguagesList languages={formattedLanguages} />
</fieldset>
)
}
LanguageSection.propTypes = {
header: React.PropTypes.string.isRequired,
languages: React.PropTypes.array.isRequired
}
ReactDOM.render(
<LanguageSection
header="Languages"
languages={languages} />,
document.getElementById('app')
)
Generated javascript
this.state = {
user: {}
};
}
componentDidMount() {
this.fetchUser();
}
fetchUser() {
$.get('/api/users/self')
.then((user) => {
this.setState({user: user});
});
}
render() {
return <h1>{this.state.user}</h1>;
}
}
This could call problems - if the callback is called after the Component is dismounted, then
this.setState won't be a function. Whenever this is the case, you should be careful to ensure your
usage of setState is cancellable.
In this example, you might wish to cancel the XHR request when the component dismounts:
Generated javascript
this.state = {
user: {},
xhr: null
};
}
componentWillUnmount() {
let xhr = this.state.xhr;
componentDidMount() {
this.fetchUser();
}
fetchUser() {
let xhr = $.get('/api/users/self')
.then((user) => {
this.setState({user: user});
});
this.setState({xhr: xhr});
}
}
Use code with caution.JavaScript
The async method is saved as a state. In the componentWillUnmount you perform all your cleanup
- including canceling the XHR request.
You could also do something more complex. In this example, I'm creating a 'stateSetter' function that
accepts the this object as an argument and prevents this.setState when the function cancel
has been called:
Generated javascript
function stateSetter(context) {
var cancelled = false;
return {
cancel: function () {
cancelled = true;
},
setState(newState) {
if (!cancelled) {
context.setState(newState);
}
}
}
}
componentWillUnmount() {
this.setter.cancel();
}
componentDidMount() {
this.fetchUser();
}
fetchUser() {
$.get('/api/users/self')
.then((user) => {
this.setter.setState({user: user});
});
}
render() {
return <h1>{this.state.user}</h1>
}
}
This works because the cancelled variable is visible in the setState closure we created.
Chapter 3: Using ReactJS with TypeScript
Section 3.1: ReactJS component written in TypeScript
Actually you can use ReactJS's components in Typescript as in facebook's example. Just replace
'jsx' file's extension to 'tsx':
Generated typescript
//helloMessage.tsx:
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
But in order to make full use of Typescript's main feature (static type checking) should be done
couple things:
Generated typescript
//helloMessage.tsx:
class HelloMessage extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}
Generated typescript
interface IHelloMessageProps {
name:string;
}
interface IHelloMessageState {
//empty in our case
}
Now Typescript will display an error if the programmer forgets to pass props. Or if they added props
that are not defined in the interface.
Generated bash
Facebook released its own package manager named Yarn, which can also be used to install React.
After installing Yarn you just need to run this command:
Generated bash
To compile your code using typescript, add/install type definition files using npm or yarn.
Generated bash
Generated bash
Generated bash
To use JSX, a language mixing javascript with html/xml, you have to change the typescript compiler
configuration. In the project's typescript configuration file (usually named tsconfig.json), you will
need to add the JSX option as:
Generated json
That compiler option basically tells the typescript compiler to translate the JSX tags in code to
javascript function calls.
To avoid typescript compiler converting JSX to plain javascript function calls, use
Generated json
"compilerOptions": {
"jsx": "preserve"
},
Generated javascript
Generated typescript
class GreeterProps {
name: string
}
Note that, the name React.SFC is an alias for React.StatelessComponent So, either can be used.
That component, however, can't access this.props since typescript can't tell if it is a react
component. To access its props, use:
Generated typescript
Even if the component doesn't have explicitly defined properties, it can now access
props.children since all components inherently have children.
Another similar good use of stateless and property-less components is in simple page templating.
The following is an examplinary simple Page component, assuming there are hypothetical Container,
NavTop and NavBottom components already in the project:
Generated typescript
In this example, the Page component can later be used by any other actual page as a base
template.
Chapter 4: State in React
Section 4.1: Basic State
State in React components is essential to manage and communicate data in your application. It is
represented as a JavaScript object and has component level scope, it can be thought of as the
private data of your component.
In the example below we are defining some initial state in the constructor function of our component
and make use of it in the render function.
Generated javascript
render() {
// We can access the greeting property through this.state
return(
<div>{this.state.greeting}</div>
);
}
}
Generated javascript
this.state = {
url: ''
}
this.onChange = this.onChange.bind(this);
}
onChange(e) {
this.setState({
url: this.props.url + '/days=?' + e.target.value
});
}
componentWillMount() {
this.setState({url: this.props.url});
}
render() {
return (
<div>
<input defaultValue={2} onChange={this.onChange} />
URL: {this.state.url}
</div>
)
}
}
The prop url is saved on state and then modified. Instead, choose to save the changes to a state,
and then build the full path using both state and props:
Generated javascript
this.state = {
days: ''
}
this.onChange = this.onChange.bind(this);
}
onChange(e) {
this.setState({
days: e.target.value
});
}
render() {
return (
<div>
<input defaultValue={2} onChange={this.onChange} />
URL: {this.props.url + '/days?=' + this.state.days}
</div>
)
}
}
This is because in a React application we want to have a single source of truth - i.e. all data is the
responsibility of one single component, and only one component. It is the responsibility of this
component to store the data within its state, and distribute the data to other components via props.
In the first example, both the MyComponent class and its parent are maintaining 'url' within their
state. If we update state.url in MyComponent, these changes are not reflected in the parent. We
have lost our single source of truth, and it becomes increasingly difficult to track the flow of data
through our application. Contrast this with the second example - url is only maintained in the state
of the parent component, and utilised as a prop in MyComponent - we therefore maintain a single
source of truth.
Parameters
1. updater: It can be an object with a number of key-value pairs that should be merged into the
state or a function that returns such an object.
2. callback (optional): a function which will be executed after setState() has been executed
successfully. Due to the fact that calls to setState() are not guaranteed by React to be
atomic, this can sometimes be useful if you want to perform some action after you are
positive that setState() has been executed successfully.
Usage:
The setState method accepts an updater argument that can either be an object with a number of
key-value-pairs that should be merged into the state, or a function that returns such an object
computed from prevState and props.
//
// An example ES6 style component, updating the state on a simple button click.
// Also demonstrates where the state can be set directly and where setState should be used.
//
class Greeting extends React.Component {
constructor(props) {
super(props);
this.click = this.click.bind(this);
// Set initial state (ONLY ALLOWED IN CONSTRUCTOR)
this.state = {
greeting: 'Hello!'
};
}
click(e) {
this.setState({
greeting: 'Hello World!'
});
}
render() {
return(
<div>
<p>{this.state.greeting}</p>
<button onClick={this.click}>Click me</button>
</div>
);
}
}
//
// This is most often used when you want to check or make use
// of previous state before updating any values.
//
this.setState(function(previousState, currentProps) {
return {
counter: previousState.counter + 1
};
});
Generated javascript
These calls may be batched together by React using Object.assign(), resulting in the counter
being incremented by 1 rather than 3.
The functional approach can also be used to move state setting logic outside of components. This
allows for isolation and re-use of state logic.
Generated javascript
// Within component
this.setState(incrementCounter);
//
// 'Hi There' will be logged to the console after setState completes
//
this.setState({ name: 'John Doe' }, () => console.log('Hi there'));
Generated javascript
handleChange(e){
this.setState({message: e.target.value});
}
render() {
return (
<div>
<legend>Type something here</legend>
<input
onChange={this.handleChange.bind(this)}
value={this.state.message}
autoFocus />
<h1>{this.state.message}</h1>
</div>
);
}
}
render(<ManagedControlDemo/>, document.querySelector('#app'));
Its very important to note the runtime behavior. Every time a user changes the value in the input field
Pop quiz, after you type a character in the input field, which DOM elements change
1. all of these - the top level div, legend, input, h1
2. only the input and h1
3. nothing
4. whats a DOM?
You can experiment with this more here to find the answer.
Basic example
Generated javascript
render() {
return <div>
<Child
text="This is the child number 1"
title="Title 1"
onClick={this.doSomething} />
<Child
text="This is the child number 2"
title="Title 2"
onClick={this.doSomething} />
</div>
}
}
As you can see in the example, thanks to props we can create reusable components.
Syntax
ES5
Generated javascript
ES6
Generated javascript
MyClass.defaultProps = {
randomObject: {},
...
}
ES7
Generated javascript
Generated code
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
optionalSymbol: React.PropTypes.symbol
If you attach isRequired to any propType then that prop must be supplied while creating the
instance of that component. If you don't provide the required propTypes then component instance
can not be created.
Syntax
ES5
Generated javascript
ES6
Generated javascript
MyClass.propTypes = {
randomObject: React.PropTypes.object,
callback: React.PropTypes.func.isRequired,
...
};
ES7
Generated javascript
In the same way, PropTypes allows you to specify more complex validation
Validating an object
Generated javascript
...
randomObject: React.PropTypes.shape({
id: React.PropTypes.number.isRequired,
text: React.PropTypes.string,
}).isRequired,
...
Generated javascript
...
arrayOfObjects: React.PropTypes.arrayOf(React.PropTypes.shape({
id: React.PropTypes.number.isRequired,
text: React.PropTypes.string,
})).isRequired,
...
Generated javascript
Where each property needs to be passed as a single prop value you could use the spread operator
... supported for arrays in ES6 to pass down all your values. The component will now look like this.
Generated javascript
Remember that the properties of the object that you pass in are copied onto the component's props.
Generated javascript
Another case is that you also can use spread operator to pass only parts of props to children
components, then you can use destructuring syntax from props again.
It's very useful when children components need lots of props but not want pass them one by one.
Generated javascript
const { foo, bar, other } = this.props // { foo: 'foo', bar: 'bar', other: 'other' };
var component = <Component {...{foo, bar}} />;
const { foo, bar } = component.props
console.log(foo, bar); // 'foo bar'
Generated javascript
Which allows us to include an arbitrary number of sub-elements when using the component later:
Generated javascript
Generated javascript
Note the use of React.cloneElement to remove the props from the child <p> tag - because props
are immutable, these values cannot be changed directly. Instead, a clone without these props must
be used.
Additionally, when adding elements in loops, be aware of how React reconciles children during a
rerender, and strongly consider including a globally unique key prop on child elements added in a
loop.
Generated javascript
The child object exposes the type property which you can compare to a specific component.
● If you are using React.createClass (ES5), 5 user defined functions are called
● If you are using class Component extends React.Component (ES6), 3 user defined
functions are called
Prop values returned by this function will be used as defaults if they are not defined when the
component is instantiated.
In the following example, this.props.name will be defaulted to Bob if not specified otherwise:
Generated javascript
getDefaultProps() {
return {
initialCount: 0,
name: 'Bob'
};
}
The return value of getInitialState() defines the initial state of the React component. The React
framework will call this function and assign the return value to this.state.
getInitialState() {
return {
count : this.props.initialCount
};
}
This function can be used to make final changes to the component before it will be added to the
DOM.
Generated javascript
componentWillMount() {
...
}
The render() function should be a pure function of the component's state and props. It returns a
single element which represents the component during the rendering process and should either be a
representation of a native DOM component (e.g. <p />) or a composite component. If nothing
should be rendered, it can return null or undefined.
This function will be recalled after any change to the component's props or state.
Generated javascript
render() {
return (
<div>
Hello, {this.props.name}!
</div>
);
}
Use code with caution.JavaScript
The component has been mounted and you are now able to access the component's DOM nodes,
e.g. via refs.
● Preparing timers
● Fetching data
● Adding event listeners
● Manipulating DOM elements
Generated javascript
componentDidMount() {
...
}
ES6 Syntax
If the component is defined using ES6 class syntax, the functions getDefaultProps() and
getInitialState() cannot be used.
Instead, we declare our defaultProps as a static property on the class, and declare the state
shape and initial state in the constructor of our class. These are both set on the instance of the class
at construction time, before any other React lifecycle function is called.
Generated javascript
this.state = {
count: this.props.initialCount
};
}
upCount() {
this.setState((prevState) => ({
count: prevState.count + 1
}));
}
render() {
return (
<div>
Hello, {this.props.name}!<br />
You clicked the button {this.state.count} times.<br />
<button onClick={this.upCount}>Click here!</button>
</div>
);
}
}
MyReactClass.defaultProps = {
name: 'Bob',
initialCount: 0
};
Replacing getDefaultProps()
Default values for the component props are specified by setting the defaultProps property of the
class:
Generated javascript
MyReactClass.defaultProps = {
name: 'Bob',
initialCount: 0
};
Replacing getInitialState()
The idiomatic way to set up the initial state of the component is to set this.state in the
constructor:
Generated javascript
constructor(props){
super(props);
this.state = {
count: this.props.initialCount
};
}
Generated javascript
componentWillUnmount(){
...
}
Generated javascript
componentWillUnmount() {
document.removeEventListener("click", this.closeMenu);
}
openMenu() {
...
}
closeMenu() {
...
}
render() {
return (
<div>
<a
href = "javascript:void(0)"
className = "closebtn"
onClick = {this.closeMenu}
>
×
</a>
<div>
Some other structure
</div>
</div>
);
}
}
When component's properties change, React will call this function with the new properties. You can
access to the old props with this.props and to the new props with nextProps.
With these variables, you can do some comparison operations between old and new props, or call
function because a property change, etc.
Generated javascript
componentWillReceiveProps(nextProps){
if (nextProps.initialCount && nextProps.initialCount > this.state.count){
this.setState({
count : nextProps.initialCount
});
}
}
shouldComponentUpdate(nextProps, nextState)
This is the second function called on properties changes and the first on state changes.
By default, if another component / your component change a property / a state of your component,
React will render a new version of your component. In this case, this function always return true.
You can override this function and choose more precisely if your component must update or
not.
In case of the function returns false, the update pipeline stops immediately.
Generated javascript
shouldComponentUpdate(nextProps, nextState){
return this.props.name !== nextProps.name ||
this.state.count !== nextState.count;
}
componentWillUpdate(nextProps, nextState)
This function works like componentWillMount(). Changes aren't in DOM, so you can do some
changes just before the update will perform.
Generated javascript
componentWillUpdate(nextProps, nextState){}
Use code with caution.JavaScript
render()
componentDidUpdate(prevProps, prevState)
Same stuff as componentDidMount() : DOM is refreshed, so you can do some work on the DOM
here.
Generated javascript
componentDidUpdate(prevProps, prevState){}
1. getDefaultProps
2. getInitialState
3. componentWillMount
4. render
5. componentDidMount
1. shouldComponentUpdate
2. componentWillUpdate
3. render
4. componentDidUpdate
1. componentWillUnmount
Presentational components are concerned only with displaying data - they can be regarded as, and
are often implemented as, functions that convert a model to a view. Typically they do not maintain
any internal state.
Container components are concerned with managing data. This may be done internally through their
own state, or by acting as intermediaries with a state-management library such as Redux. The
container component will not directly display data, rather it will pass the data to a presentational
component.
Generated javascript
// Container component
import React, { Component } from 'react';
import Api from 'path/to/api';
componentDidMount() {
// Make API call and update state with returned comments
Api.getComments().then(comments => this.setState({ comments }));
}
render() {
// Pass our state comments to the presentational component
return (
<CommentsList comments={this.state.comments} />
);
}
}
// Presentational Component
const CommentsList = ({ comments }) => (
<div>
{comments.map(comment => (
<div>{comment}</div>
))}
</div>
);
CommentsList.propTypes = {
comments: React.PropTypes.arrayOf(React.PropTypes.string)
}
Generated javascript
this.onChange = this.onChange.bind(this);
this.state = {
name: ''
};
}
onChange(e) {
this.setState({
name: e.target.value
});
}
render() {
return (
<div>
<label htmlFor='name-input'>Name: </label>
<input
id='name-input'
onChange={this.onChange}
value={this.state.name} />
</div>
)
}
}
The above example demonstrates how the value property defines the current value of the input and
the onChange event handler updates the component's state with the user's input.
Form inputs should be defined as controlled components where possible. This ensures that the
component state and the input value is in sync at all times, even if the value is changed by a trigger
other than a user input.
Section 7.2: Uncontrolled Components
Uncontrolled components are inputs that do not have a value property. In opposite to controlled
components, it is the application's responsibility to keep the component state and the input value in
sync.
Generated javascript
this.onChange = this.onChange.bind(this);
this.state = {
name: 'John'
};
}
onChange(e) {
this.setState({
name: e.target.value
});
}
render() {
return (
<div>
<label htmlFor='name-input'>Name: </label>
<input
id='name-input'
onChange={this.onChange}
defaultValue={this.state.name} />
</div>
)
}
}
Here, the component's state is updated via the onChange event handler, just as for controlled
components. However, instead of a value property, a defaultValue property is supplied. This
determines the initial value of the input during the first render. Any subsequent changes to the
component's state are not automatically reflected by the input value; If this is required, a controlled
component should be used instead.
Chapter 8: React Boilerplate [React + Babel + Webpack]
Section 8.1: react-starter project
About this Project
This is simple boilerplate project. This post will guide you to set up the environment for ReactJs +
Webpack + Bable.
we will need node package manager for fire up express server and manage dependencies
throughout the project. if you are new to node package manager, you can check here. Note :
Installing node package manager is require here.
Create a folder with suitable name and navigate into it from terminal or by GUI.Then go to terminal
and type npm init this will create a package.json file, Nothing scary , it will ask you few question
like name of your project ,version, description, entry point, git repository, author, license etc. Here
entry point is important because node will initially look for it when you run the project. At the end it
will ask you to verify the information you provide. You can type yes or modify it. Well that's it , our
package.json file is ready.
Express server setup run npm install express@4 --save. This is all the dependencies we
needed for this project.Here save flag is important, without it package.js file will not be updated. Main
task of package.json is to store list of dependencies. It will add express version 4. Your package.json
will look like "dependencies": { "express": "^4.13.4", ............. },
After complete download you can see there is node_modules folder and sub folder of our
dependencies. Now on the root of project create new file server.js file. Now we are setting express
server. I am going to past all the code and explain it later.
Generated javascript
app.use(express.static('public'));
app.listen(3000, function () {
console.log('Express server is using port:3000');
});
var express = require('express'); this will gave you the access of entire express api.
var app = express(); will call express library as function. app.use(); let the add the
functionality to your express application. app.use(express.static('public')); will specify the
folder name that will be expose in our web server. app.listen(port, function(){}) will here
our port will be 3000 and function we are calling will verify that out web server is running properly.
That's it express server is set up.
Now go to our project and create a new folder public and create index.html file. index.html is the
default file for you application and Express server will look for this file. The index.html is simple html
file which looks like
Generated html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
</head>
<body>
<h1>hello World</h1>
</body>
</html>
And go to the project path through the terminal and type node server.js. Then you will see *
console.log('Express server is using port:3000');*.
Go to the browser and type http://localhost:3000 in nav bar you will see hello World.
Now go inside the public folder and create a new file app.jsx. JSX is a preprocessor step that adds
XML syntax to your JavaScript.You can definitely use React without JSX but JSX makes React a lot
more elegant. Here is the sample code for app.jsx
Generated javascript
ReactDOM.render(
<h1>Hello World!!!</h1>,
document.getElementById('app')
);
Now go to index.html and modify the code , it should looks like this
Generated html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/babel" src="app.jsx"></script>
</body>
</html>
With this in place you are all done, I hope you find it simple.
You can also use Node Version Manager to better manage your node and npm versions. It is great
for testing your project on different node versions. However, it is not recommended for production
environment.
Once you have installed node on your system, go ahead and install some essential packages to
blast off your first React project using Babel and Webpack.
Before we actually start hitting commands in the terminal. Take a look at what Babel and Webpack
are used for.
You can start your project by running npm init in your terminal. Follow the initial setup. After that,
run following commands in your terminal-
Dependencies:
Generated bash
Dev Dependecies:
Generated bash
Generated bash
Generated json
{
"presets": ["es2015", "stage-0", "react"]
}
Generated json
{
"ecmaFeatures": {
"jsx": true,
"modules": true
},
"env": {
"browser": true,
"node": true
},
"parser": "babel-eslint",
"rules": {
"quotes": [2, "single"],
"strict": [2, "never"]
},
"plugins": [
"react"
]
}
Create a .gitignore file to prevent uploading generated files to your git repo.
Generated code
node_modules
npm-debug.log
.DS_Store
dist
Generated javascript
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
'./src/index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
module: {
loaders: [{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
include: path.join(__dirname, 'src')
}]
}
};
And finally, create a sever.js file to be able to run npm start, with following contents:
Generated javascript
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
historyApiFallback: true
}).listen(3000, 'localhost', function (err, result) {
if (err) {
return console.log(err);
}
Generated javascript
Run node server.js or npm start in the terminal, if you have defined what start stands for in your
package.json.
Chapter 9: Using ReactJS with jQuery
Section 9.1: ReactJS with jQuery
Firstly, you have to import jquery library . We also need to import findDOmNode as we’re going to
manipulate the dom. And obviously we are importing React as well.
Generated javascript
We are setting an arrow function ‘handleToggle’ that will fire when an icon will be clicked. We’re just
showing and hiding a div with a reference naming ‘toggle’ onClick over an icon.
Generated javascript
handleToggle = () => {
const el = findDOMNode(this.refs.toggle);
$(el).slideToggle();
};
Generated jsx
Generated jsx
handleToggle = () => {
const el = findDOMNode(this.refs.toggle);
$(el).slideToggle();
};
render() {
return (
<div className=”long-desc”>
<ul className=”profile-info”>
<li>
<span className=”info-title”>User Name : </span> Shuvo Habib
</li>
</ul>
<ul className=”profile-info additional-profile-info-list” ref=”toggle”>
<li>
<span className=”info-email”>Office Email</span> [email protected]
</li>
</ul>
We are done! This is the way, how we can use jQuery in React component.
Chapter 10: React Routing
Section 10.1: Example Routes.js file, followed by use of Router
Link in component
Place a file like the following in your top level directory. It defines which components to render for
which paths.
Generated javascript
export default(
<Route path="/" component={App}>
<IndexRoute component={Index} />
<Route path="posts/new" component={New} />
<Route path="posts/:id" component={Show} />
</Route>
);
Now in your top level index.js that is your entry point to the app, you need only render this Router
component like so:
Generated javascript
// entry point
ReactDOM.render(
<Router history={browserHistory} routes={routes} />
, document.getElementById('main'));
Generated javascript
export default(
<Route path="/" component={App}>
<IndexRoute component={Index} />
<Route path="/contact" {...ContactComponent()} />
<Route path="/about" {...groupedComponents('about')} />
<Route path="/tos" {...groupedComponents('tos')} />
</Route>
);
In the example below we have three different components and one connected component.
● UserInputForm: This component display an input field And when the field value changes, it
calls inputChange method on props (which is provided by the parent component) and if the
data is provided as well, it displays that in the input field.
● UserDashboard: This component displays a simple message and also nests
UserInputForm component, It also passes inputChange method to UserInputForm
component, UserInputForm component inturn makes use of this method to communicate
with the parent component.
● UserDashboardConnected: This component just wraps the UserDashboard component
using ReactRedux connect method., This makes it easier for us to manage the component
state and update the component when the state changes.
● App: This component just renders the UserDashboardConnected component.
Generated javascript
return(
<form action="" onSubmit={handleSubmit}>
<label htmlFor="name">Please enter your name</label>
<br />
<input type="text" id="name" defaultValue={props.data.name || ''} onChange={
props.inputChange } />
</form>
)
}
return(
<div>
<h1>Hi { props.user.name || 'User' }</h1>
<UserInputForm data={props.user} inputChange={inputChangeHandler} />
</div>
)
}
ReactDOM.render(
<Provider store={ store }>
<App />
</Provider>,
document.getElementById('application')
);
JS Bin URL
Chapter 12: How to setup a basic webpack, react and
babel environment
Section 12.1: How to build a pipeline for a customized "Hello
world" with images
Step 1: Install Node.js
The build pipeline you will be building is based in Node.js so you must ensure in the first instance
that you have this installed. For instructions on how to install Node.js you can checkout the SO docs
for that here.
Open your project folder on the command line and use the following command:
Generated bash
npm init
For the purposes of this example you can feel free to take the defaults or if you'd like more info on
what all this means you can check out this SO doc on setting up package configuration.
Run the following command on the command line to install the packages necessary for this example:
Generated bash
Generated bash
npm install --save-dev babel-core babel-preset-react babel-preset-es2015 webpack babel-loader
css-loader style-loader file-loader image-webpack-loader
Finally webpack and webpack-dev-server are things that are worth installing globally rather than as a
dependency of your project, if you'd prefer to add it as a dependency then that will work to, I don't.
Here is the command to run:
Generated bash
This will setup babel to use the presets you've just installed. Your .babelrc file should look like this:
Generated json
{
"presets": ["react", "es2015"]
}
Set yourself up a directory stucture that looks like the below in the root of your directory:
Generated code
|- node_modules
|- src/
|- components/
|- images/
|- styles/
|- index.html
|- index.jsx
|- .babelrc
|- package.json
Step 5: Populate the project with the Hello World project files
This isn't really important to the process of building a pipeline so I'll just give you the code for these
and you can copy paste them in:
src/components/HelloWorldComponent.jsx
Generated jsx
handleChange(e) {
this.setState({name: e.target.value});
}
render() {
return (
<div>
<div className="image-container">
<img src="./images/myImage.gif" />
</div>
<div className="form">
<input type="text" onChange={this.handleChange} />
<div>
My name is {this.state.name} and I'm a clever cloggs because I built a React build pipeline
</div>
</div>
</div>
);
}
}
src/images/myImage.gif
Feel free to substitute this with any image you'd like it's simply there to prove the point that we can
bundle up images as well. If you provide your own image and you name it something different then
you'll have to update the HelloWorldComponent.jsx to reflect your changes. Equally if you choose an
image with a different file extension then you need to modify the test property of the image loader in
the webpack.config.js with appropriate regex to match your new file extension..
src/styles/styles.css
Generated css
.form {
margin: 25px;
padding: 25px;
border: 1px solid #ddd;
background-color: #eaeaea;
border-radius: 10px;
}
.form div {
padding-top: 25px;
}
.image-container {
display: flex;
justify-content: center;
}
index.html
Generated html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Learning to build a react pipeline</title>
</head>
<body>
<div id="content"></div>
<script src="app.js"></script>
</body>
</html>
Generated jsx
require('./images/myImage.gif');
require('./styles/styles.css');
require('./index.html');
Create a file called webpack.config.js in the root of your project and copy this code into it:
webpack.config.js
Generated javascript
var config = {
context: path.resolve(__dirname + '/src'),
entry: './index.jsx',
output: {
filename: 'app.js',
path: path.resolve(__dirname + '/dist'),
},
devServer: {
contentBase: path.join(__dirname + '/dist'),
port: 3000,
open: true,
},
module: {
loaders: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.css$/,
loader: "style!css"
},
{
test: /\.gif$/,
loaders: [
'file?name=[path][name].[ext]',
'image-webpack',
]
},
{
test: /\.(html)$/,
loader: "file?name=[path][name].[ext]"
}
],
},
};
module.exports = config;
To do this you will need to add two properties to the scripts key of the JSON defined in the
package.json file in the root of your project. Make your scripts key look like this:
Generated json
"scripts": {
"start": "webpack-dev-server",
"build": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
The test script will have already been there and you can choose whether to keep it or not, it's not
important to this example.
From the command line, if you are in the project root directory you should now be able to run the
command:
Generated bash
npm run build
This will bundle up the little application you've built and place it in the dist/ directory that it will
create in the root of your project folder.
Generated bash
npm start
Then the application you've built will be served up in your default web browser inside of a webpack
dev server instance.
Chapter 13: React.createClass vs extends
React.Component
Section 13.1: Create React Component
Let's explore the syntax differences by comparing two code examples.
React.createClass (deprecated)
Here we have a const with a React class assigned, with the render function following on to
complete a typical base component definition.
Generated javascript
React.Component
Let's take the above React.createClass definition and convert it to use an ES6 class.
Generated javascript
In this example we're now using ES6 classes. For the React changes, we now create a class called
MyComponent and extend from React.Component instead of accessing React.createClass
directly. This way, we use less React boilerplate and more JavaScript.
PS: Typically this would be used with something like Babel to compile the ES6 to ES5 to work in
other browsers.
React.createClass
Note the onClick declaration with the this.handleClick method bound. When this method gets
called React will apply the right execution context to the handleClick.
Generated javascript
React.Component
With ES6 classes this is null by default, properties of the class do not automatically bind to the
React class (component) instance.
Generated javascript
There are a few ways we could bind the right this context.
Generated javascript
Another approach is changing the context of this.handleClick inside the constructor. This way we
avoid inline repetition. Considered by many as a better approach that avoids touching JSX at all:
Generated javascript
You can also use ES6 anonymous function without having to bind explicitly:
Generated javascript
React.createClass
In this version, the propTypes property is an Object in which we can declare the type for each prop.
The getDefaultProps property is a function that returns an Object to create the initial props.
Generated javascript
React.Component
This version uses propTypes as a property on the actual MyComponent class instead of a property
as part of the createClass definition Object.
The getDefaultProps has now changed to just an Object property on the class called
defaultProps, as it's no longer a "get" function, it's just an Object. It avoids more React boilerplate,
this is just plain JavaScript.
Generated javascript
MyComponent.propTypes = {
name: React.PropTypes.string,
position: React.PropTypes.number
};
MyComponent.defaultProps = {
name: 'Home',
position: 1
};
Additionally, there is another syntax for propTypes and defaultProps. This is a shortcut if your
build has ES7 property initializers turned on:
Generated javascript
React.createClass
In this version we can add mixins to components using the mixins property which takes an Array of
available mixins. These then extend the component class.
Generated javascript
var MyMixin = {
doSomething() {
}
};
React.Component
React mixins are not supported when using React components written in ES6. Moreover, they will
not have support for ES6 classes in React. The reason is that they are considered harmful.
React.createClass
Generated javascript
React.Component
In this version we declare all state as a simple initialisation property in the constructor, instead of
using the getInitialState function. It feels less "React API" driven since this is just plain
JavaScript.
Generated javascript
Section 13.6: ES6/React this keyword with ajax to get data from
server
Generated javascript
showResults(response){
this.setState({
searchResults: response.results
})
}
search(url){
$.ajax({
type: "GET",
dataType: 'jsonp',
url: url,
success: (data) => {
this.showResults(data);
},
error: (xhr, status, err) => {
console.error(url, status, err.toString());
}
});
}
render() {
return (
<div>
<SearchBox search={this.search.bind(this)} />
<Results searchResults={this.state.searchResults} />
</div>
);
}
}
Generated javascript
componentDidMount () {
request
.get('/search')
.query({ query: 'Manny' })
.query({ range: '1..5' })
.query({ order: 'desc' })
.set('API-Key', 'foobar')
.set('Accept', 'application/json')
.end((err, resp) => {
if (!err) {
this.setState({someData: resp.text})
}
})
}
render() {
return (
<div>{this.state.someData || 'waiting for response...'}</div>
)
}
}
The .query() method accepts objects, which when used with the GET method will form a
query-string. The following will produce the path
/search?query=Manny&range=1..5&order=desc.
POST requests
Generated javascript
request.post('/user')
.set('Content-Type', 'application/json')
.send('{"name":"tj","pet":"tobi"}')
.end(callback)
We make an AJAX request using fetch, which is build into most browsers. Use a fetch polyfill in
production to support older browsers. You can also use any other library for making requests (e.g.
axios, SuperAgent, or even plain Javascript).
We set the data we receive as component state, so we can access it inside the render method.
There, we loop through the data using map. Don't forget to always add a unique key attribute (or
prop) to the looped element, which is important for React's rendering performance.
Generated javascript
componentDidMount() {
fetch('/api/users')
.then(response => response.json())
.then(json => this.setState({ users: json.data }));
}
render() {
return (
<div>
<h1>Users</h1>
{
this.state.users.length == 0
? 'Loading users...'
: this.state.users.map(user => (
<figure key={user.id}>
<img src={user.avatar} />
<figcaption>
{user.name}
</figcaption>
</figure>
))
}
</div>
);
}
}
Generated javascript
componentDidMount () {
var request = new XMLHttpRequest();
request.open('GET', '/my/url', true);
request.onload = () => {
if (request.status >= 200 && request.status < 400) {
// Success!
this.setState({someData: request.responseText})
} else {
// We reached our target server, but it returned an error
// Possibly handle the error by changing your state.
}
};
request.onerror = () => {
// There was a connection error of some sort.
// Possibly handle the error by changing your state.
};
request.send();
}
render() {
return (
<div>{this.state.someData || 'waiting for response...'}</div>
)
}
}
In this example, we will change the Parent state by passing a function to the Child component and
invoking that function inside the Child component.
Generated javascript
outputEvent(event) {
// the event context comes from the Child
this.setState({ count: this.state.count++ });
}
render() {
const variable = 5;
return (
<div>
Count: { this.state.count }
<Child clickHandler={this.outputEvent} />
</div>
);
}
}
Note that the Parent's outputEvent method (that changes the Parent state) is invoked by the
Child's button onClick event.
Those are the 2 basic operations of any event system: subscribe/listen to an event to be notify, and
send/trigger/publish/dispatch a event to notify the ones who wants.
There are at least 3 patterns to do that. You can find a comparison here.
You can pass props down to child components. In this example message is the prop that we pass
down to the child component, the name message is chosen arbitrarily, you can name it anything you
want.
Generated javascript
Here, the <Parent /> component renders two <Child /> components, passing message for child
inside the first component and 5 inside the second one.
Chapter 16: Stateless Functional Components
Section 16.1: Stateless Functional Component
Components let you split the UI into independent, reusable pieces. This is the beauty of React; we
can separate a page into many small reusable components.
Prior to React v14 we could create a stateful React component using React.Component (in ES6), or
React.createClass (in ES5), irrespective of whether it requires any state to manage data or not.
React v14 introduced a simpler way to define components, usually referred to as stateless
functional components. These components use plain JavaScript functions.
For example:
Generated javascript
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
This function is a valid React component because it accepts a single props object argument with
data and returns a React element. We call such components functional because they are literally
JavaScript functions.
Stateless functional components typically focus on UI; state should be managed by higher-level
“container” components, or via Flux/Redux etc. Stateless functional components don’t support state
or lifecycle methods.
Benefits:
Let's say we have a page that can register a user, search for registered users, or display a list of all
the registered users.
Generated javascript
ReactDOM.render(
<HomePage/>,
document.getElementById('app')
);
The HomePage component provides the UI to register and search for users. Note that it is a typical
React component including state, UI, and behavioral code. The data for the list of registered users is
stored in the state variable, but our reusable List (shown below) encapsulates the UI code for the
list.
homepage.js:
Generated javascript
constructor(props) {
super();
this.state={users:[], showSearchResult: false, searchResult: []};
}
registerClick(){
let users = this.state.users.slice();
if(users.indexOf(this.refs.mail_id.value) == -1){
users.push(this.refs.mail_id.value);
this.refs.mail_id.value = '';
this.setState({users});
}else{
alert('user already registered');
}
}
searchClick(){
let users = this.state.users;
let index = users.indexOf(this.refs.search.value);
if(index >= 0){
this.setState({searchResult: users[index], showSearchResult: true});
}else{
alert('no user found with this mail id');
}
}
hideSearchResult(){
this.setState({showSearchResult: false});
}
render() {
return (
<div>
<input placeholder='email-id' ref='mail_id'/>
<input type='submit' value='Click here to register' onClick={this.registerClick.bind(this)}/>
<input style={{marginLeft: '100px'}} placeholder='search' ref='search'/>
<input type='submit' value='Click here to register' onClick={this.searchClick.bind(this)}/>
{this.state.showSearchResult ?
<div>
Search Result:
<List users={[this.state.searchResult]}/>
<p onClick={this.hideSearchResult.bind(this)}>Close this</p>
</div>
:
<div>
Registered users:
<br/>
{this.state.users.length ?
<List users={this.state.users}/>
:
"no user is registered"
}
</div>
}
</div>
);
}
}
Finally, our stateless functional component List, which is used display both the list of registered
users and the search results, but without maintaining any state itself.
list.js:
Generated javascript
Reference: https://facebook.github.io/react/docs/components-and-props.html
Chapter 17: Performance
Section 17.1: Performance measurement with ReactJS
You can't improve something you can't measure. To improve the performance of React
components, you should be able to measure it. ReactJS provides with addon tools to measure
performance. Import the react-addons-perf module to measure the performance.
Generated javascript
You can use below methods from the imported Perf module:
● Perf.printInclusive()
● Perf.printExclusive()
● Perf.printWasted()
● Perf.printOperations()
● Perf.printDOM()
The most important one which you will need most of the time is Perf.printWasted() which gives
you the tabular representation of your individual component's wasted time.
You can note the Wasted time column in the table and improve Component's performance using
Tips & Tricks section above.
Refer the React Official Guide and excellent article by Benchling Engg. on React Performance.
1. Two components of the same class will generate similar trees and two components of
different classes will generate different trees.
2. It is possible to provide a unique key for elements that is stable across different renders.
Moreover, what follows is crucial and extremely important to understand if you want to optimise
performance.
If they [two nodes] are not of the same type, React is not going to even try at matching
what they render. It is just going to remove the first one from the DOM and insert the
second one.
Here's why:
It is very unlikely that a element is going to generate a DOM that is going to look like what
a would generate. Instead of spending time trying to match those two structures, React
just re-builds the tree from scratch.
In other words:
The HTML DOM is a standard for how to get, change, add, or delete HTML elements.
So React's team came up with the idea to abstract the HTML DOM and create its own Virtual DOM
in order to compute the minimum number of operations we need to apply on the HTML DOM to
replicate current state of our application.
How Exactly?
At each point of time, React has the application state represented as a Virtual DOM. Whenever
application state changes, these are the steps that React performs in order to optimise performance
1. Generate a new Virtual DOM that represents the new state of our application
2. Compare the old Virtual DOM (which represents the current HTML DOM) vs the new Virtual
DOM
3. Based on 2. find the minimum number of operations to transform the old Virtual DOM (which
represents the current HTML DOM) into the new Virtual DOM
○ to learn more about that - read React's Diff Algorithm
4.
5. After those operations are found, they are mapped into their equivalent HTML DOM
operations
○ remember, the Virtual DOM is only an abstraction of the HTML DOM and there is a
isomorphic relation between them
6.
7. Now the minimum number of operations that have been found and transferred to their
equivalent HTML DOM operations are now applied directly onto the application's HTML
DOM, which saves time from modifying the HTML DOM unnecessarily.
Note: Operations applied on the Virtual DOM are cheap, because the Virtual DOM is a JavaScript
Object.
1. If you see yourself alternating between two components classes with very similar output, you
may want to make it the same class.
2. Use shouldComponentUpdate to prevent component from rerender, if you know it is not
going to change, for example
3. Generated javascript
renderToString
This will render React components to HTML on server. This function will also add data-react-
properties to HTML elements so React on client won't have to render elements again.
Generated javascript
renderToString(<App />);
renderToStaticMarkup
This will render React components to HTML, but without data-react- properties, it is not
recommended to use components that will be rendered on client, because components will rerender.
Generated javascript
renderToStaticMarkup(<App />);
Filename: src/index.jsx
Generated jsx
render() {
Filename: webpack.config.js
Generated javascript
module.exports = {
devtool: "source-map",
output: {
filename: "bundle.js"
},
module: {
loaders: [
]
}
Filename: .babelrc
Generated json
"presets": ["es2015","react"]
Filename: index.html
Generated html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="App"></div>
<script src="build/bundle.js" charset="utf-8"></script>
</body>
</html>
Generated bash
$ webpack
type Props = {
posts: Array<Article>,
dispatch: Function,
children: ReactElement
const AppContainer =
<div className="main-app">
{children}
</div>
posts: Array<Article>,
dispatch: Function,
children: ReactElement
props: Props;
render () {
JavaScript Expressions
You can pass any JavaScript expression as a prop, by surrounding it with {}. For example, in this
JSX:
Generated jsx
Inside the MyComponent, the value of props.count will be 10, because the expression 1 + 2 + 3
+ 4 gets evaluated.
If statements and for loops are not expressions in JavaScript, so they can't be used in JSX
directly.
String Literals
Of course, you can just pass any string literal as a prop too. These two JSX expressions are
equivalent:
Generated jsx
When you pass a string literal, its value is HTML-unescaped. So these two JSX expressions are
equivalent:
Generated jsx
This behavior is usually not relevant. It's only mentioned here for completeness.
If you pass no value for a prop, it defaults to true. These two JSX expressions are equivalent:
Generated jsx
However, the React team says in their docs using this approach is not recommended, because it
can be confused with the ES6 object shorthand {foo} which is short for {foo: foo} rather than
{foo: true}. They say this behavior is just there so that it matches the behavior of HTML.
Spread Attributes
If you already have props as an object, and you want to pass it in JSX, you can use ... as a spread
operator to pass the whole props object. These two components are equivalent:
Generated javascript
function Case1() {
function Case2() {
String Literals
You can put a string between the opening and closing tags and props.children will just be that
string. This is useful for many of the built-in HTML elements. For example:
Generated jsx
<MyComponent>
<h1>Hello world!</h1>
</MyComponent>
This is valid JSX, and props.children in MyComponent will simply be <h1>Hello world!</h1>.
Note that the HTML is unescaped, so you can generally write JSX just like you would write HTML.
JSX Children
You can provide more JSX elements as the children. This is useful for displaying nested
components:
Generated jsx
<MyContainer>
<MyFirstComponent />
<MySecondComponent />
</MyContainer>
You can mix together different types of children, so you can use string literals together with JSX
children. This is another way in which JSX is like HTML, so that this is both valid JSX and valid
HTML:
Generated jsx
<div>
<h2>Here is a list</h2>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
Note that a React component can't return multiple React elements, but a single JSX expression
can have multiple children. So if you want a component to render multiple things you can wrap
them in a div like the example above.
JavaScript Expressions
You can pass any JavaScript expression as children, by enclosing it within {}. For example, these
expressions are equivalent:
Generated jsx
<MyComponent>foo</MyComponent>
<MyComponent>{'foo'}</MyComponent>
This is often useful for rendering a list of JSX expressions of arbitrary length. For example, this
renders an HTML list:
Generated javascript
);
return (
<ul>
</ul>
);
};
Note that JavaScript expressions can be mixed with other types of children.
Functions as Children
Normally, JavaScript expressions inserted in JSX will evaluate to a string, a React element, or a list
of those things. However, props.children works just like any other prop in that it can pass any sort
of data, not just the sorts that React knows how to render. For example, if you have a custom
component, you could have it take a callback as props.children:
Generated javascript
<Repeat numTimes={10}>
</Repeat>
);
items.push(children(i));
return <div>{items}</div>;
};
Children passed to a custom component can be anything, as long as that component transforms
them into something React can understand before rendering. This usage is not common, but it works
if you want to stretch what JSX is capable of.
Ignored Values
Note that false, null, undefined, and true are valid children. But they simply don't render. These
JSX expressions will all render to the same thing:
Generated jsx
<MyComponent />
<MyComponent></MyComponent>
<MyComponent>{false}</MyComponent>
<MyComponent>{null}</MyComponent>
<MyComponent>{true}</MyComponent>
This is extremely useful to conditionally render React elements. This JSX only renders a if
showHeader is true:
Generated jsx
<div>
<Content />
</div>
One important caveat is that some "falsy" values, such as the 0 number, are still rendered by React.
For example, this code will not behave as you might expect because 0 will be printed when
props.messages is an empty array:
Generated jsx
<div>
{props.messages.length &&
</div>
One approach to fix this is to make sure that the expression before the && is always boolean:
Generated jsx
<div>
</div>
Lastly, bare in mind that if you want a value like false, true, null, or undefined to appear in the
output, you have to convert it to a string first:
Generated jsx
<div>
</div>
Generated javascript
constructor() {
super();
this.state = {
person: {
firstName: '',
lastName: ''
handleChange(event) {
person[event.target.name] = event.target.value;
this.setState({person});
render() {
return (
<form>
<input
type="text"
name="firstName"
value={this.state.firstName}
onChange={this.handleChange.bind(this)} />
<input
type="text"
name="lastName"
value={this.state.lastName}
onChange={this.handleChange.bind(this)} />
</form>
In this example we initialize state with an empty person object. We then bind the values of the 2
inputs to the individual keys of the person object. Then as the user types, we capture each value in
the handleChange function. Since the values of the components are bound to state we can rerender
as the user types by calling setState().
NOTE: Not calling setState() when dealing with controlled components, will cause the user to
type, but not see the input because React only renders changes when it is told to do so.
It's also important to note that the names of the inputs are same as the names of the keys in the
person object. This allows us to capture the value in dictionary form as seen here.
Generated javascript
handleChange(event) {
person[event.target.name] = event.target.value;
this.setState({person});
constructor(props) {
super(props);
render() {
return React.createElement(
'section', this.props
);
constructor(props) {
super(props);
render(...elements) {
tabIndex: -1
}, this.props);
if (css != '') {
elements.unshift(React.createElement(
'style', null,
css
));
return React.createElement(
'div', props,
...elements
);
}
static title() {
return '';
static css() {
return '';
constructor(props) {
super(props);
}
render() {
}, this.props);
return React.createElement(
'li', props,
React.createElement(
'span', props,
props.panelClass.title()
);
panelClass property of Tab instance must contain class of panel used for description.
super(props);
this.setState({
panels: props.panels
});
render() {
this.tabSet = [];
this.panelSet = [];
this.tabSet.push(React.createElement(
Tab, {
name: panelData.name,
active: tabIsActive,
panelClass: panelData.class,
));
this.panelSet.push(React.createElement(
panelData.class, {
id: panelData.name,
active: tabIsActive,
));
return React.createElement(
React.createElement(
'nav', null,
React.createElement(
'ul', null,
...this.tabSet
),
...this.panelSet
);
openTab(name) {
this.findDOMNode(this.refs.activePanel).focus();
}
panels property of PanelGroup instance must contain array with objects. Every object there
declares important data about panels:
Clarification
When tab is down, needed panel is getting class name active on DOM element (means that it
gonna be visible) and it's focused now.
constructor(props) {
super(props);
render() {
return React.createElement(
'main', null,
React.createElement(
React.createElement(
PanelGroup, {
panels: [
name: 'console',
panelClass: ConsolePanel
},
name: 'figures',
panelClass: FiguresPanel
],
activeTab: 'console'
),
React.createElement(
React.createElement(
PanelGroup, {
panels: [
name: 'properties',
panelClass: PropertiesPanel
],
activeTab: 'properties'
);
constructor(props) {
super(props);
static title() {
return 'Console';
}
class FiguresPanel extends Panel {
constructor(props) {
super(props);
static title() {
return 'Figures';
constructor(props) {
super(props);
static title() {
return 'Properties';
1. Action — simple object describing action type and other input data.
2. Dispatcher — single action receiver and callbacks controller. Imagine it is central hub of
your application.
3. Store — contains the application state and logic. It registers callback in dispatcher and emits
event to view when change to the data layer has occurred.
4. View — React component that receives change event and data from store. It causes
re-rendering when something is changed.
As of Flux data flow, views may also create actions and pass them to dispatcher for user
interactions.
Reverted
● Different React components (views) get data from different stores about made changes.
Few components may be called controller-views, cause they provide the glue code to
get the data from the stores and to pass data down the chain of their descendants.
Controller-views represent any significant section of the page.
● Stores can be remarked as callbacks that compare action type and other input data for
business logic of your application.
● Dispatcher is common actions receiver and callbacks container.
● Actions are nothing than simple objects with required type property.
Formerly, you'll want to use constants for action types and helper methods (called action
creators).
Chapter 25: React, Webpack & TypeScript installation
Section 25.1: webpack.config.js
Generated javascript
module.exports = {
entry: './src/index',
output: {
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/
}]
},
resolve: {
};
The main components are (in addition to the standard entry, output and other webpack properties):
The loader
For this you need to create a rule that tests for the .ts and .tsx file extensions, specify ts-loader
as the loader.
Resolve TS extensions
You also need to add the .ts and .tsx extensions in the resolve array, or webpack won't see them.
Generated json
"include": [
"src/*"
],
"compilerOptions": {
"target": "es5",
"jsx": "react",
"allowSyntheticDefaultImports": true
include
This is an array of source code. Here we have only one entry, src/*, which specifies that everything
in the src directory is to be included in compilation.
compilerOptions.target
Specifies that we want to compile to ES5 target.
compilerOptions.jsx
Setting this to true will make TypeScript automatically compile your tsx syntax from <div /> to
React.createElement("div").
compilerOptions.allowSyntheticDefaultImports
Handy property which will allow you to import node modules as if they are ES6 modules, so instead
of doing
Generated javascript
Generated javascript
without any errors telling you that React has no default export.
interface AppProps {
name: string;
}
interface AppState {
words: string[];
constructor() {
super();
this.state = {
};
render() {
When using TypeScript with React, once you've downloaded the React DefinitelyTyped type
definitions (npm install --save @types/react), every component will require you to add type
annotations.
You do this like so:
Generated typescript
where AppProps and AppState are interfaces (or type aliases) for your components' props and
state respectively.
Chapter 26: How and why to use keys in React
Whenever you are rendering a list of React components, each component needs to have a key
attribute. The key can be any value, but it does need to be unique to that list.
When React has to render changes on a list of items, React just iterates over both lists of children at
the same time and generates a mutation whenever there's a difference. If there are no keys set for
the children, React scans each child. Otherwise, React compares the keys to know which were
added or removed from the list.
Generated javascript
function SomeComponent(props){
function getItemsList(){
return (
<ul>
{getItemsList()}
</ul>
);
Generated html
<ul>
<li key='cat'>cat</li>
<li key='dog'>dog</li>
<li key='rat'>rat</li>
</ul>
So if you are iterating over an array to show a list of li elements, each of the li elements needs a
unique identifier specified by the key property. This usually can be the id of your database item or
the index of the array.
Each todo item has a text and id property. Imagine that the id property comes from a backend
datastore and is a unique numeric value:
Generated javascript
todos = [
id: 1,
},
id: 2,
},
id: 3,
id: 4,
},
];
We set the key attribute of each iterated list element to todo-${todo.id} so that react can identify
it internally:
Generated javascript
render() {
return (
<ul>
{ todos.map((todo) =>
{ todo.text }
</li>
)}
</ul>
);
Generated javascript
render() {
return (
<ul>
{ todo.text }
</li>
)}
</ul>
);
A HOC is a pure javascript function that accepts a component as it's argument and returns a new
component with the extended functionality.
AuthenticatedComponent.js
Generated javascript
/**
* has to be set from your application logic (or use react-redux to retrieve it from global
* state).
*/
isAuthenticated() {
return this.props.isAuthenticated;
/**
* Render
*/
render() {
const loginErrorMessage = (
<div>
</div>
);
return (
<div>
</div>
);
};
MyPrivateComponent.js
Generated javascript
/**
* Render
*/
render() {
return (
<div>
</div>
);
hocLogger.js
Generated javascript
componentDidMount() {
render() {
MyLoggedComponent.js
Generated javascript
return (
<div>
</div>
);
Generated javascript
Use connect to connect component to Redux store and pull props from store to component.
Generated javascript
mapStateToProps,
mapDispatchToProps
)(TodoList)
Generated javascript
/*
* action types
*/
Handle these messages and create a new state for the store in reducer functions.
Generated javascript
switch (action.type) {
case SET_VISIBILITY_FILTER:
visibilityFilter: action.filter
})
default:
return state
This example assumes code to be in src/ and the output to be put into out/. As such the folder
structure should look something like
Generated code
example/
|-- src/
| |-- index.js
| `-- ...
|-- out/
`-- package.json
Assuming a setup npm environment, we first need to setup babel in order to transpile the React
code into es5 compliant code.
Generated bash
The above command will instruct npm to install the core babel libraries as well as the loader module
for use with webpack. We also install the es6 and react presets for babel to understand JSX and es6
module code. (More information about the presets can be found here Babel presets)
Generated bash
$npm i -D webpack
Use code with caution.Bash
This command will install webpack as a development dependency. (i is the shorthand for install and
-D the shorthand for --save-dev)
You might also want to install any additional webpack packages (such as additional loaders or the
webpack-dev-server extension)
Generated bash
Setting up webpack
With the dependencies setup we will need a webpack.config.js file to tell webpack what to do.
simple webpack.config.js:
Generated javascript
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
};
This file tells webpack to start with the index.js file (assumed to be in src/) and convert it into a
single bundle.js file in the out directory.
The module block tells webpack to test all files encountered against the regular expression and if
they match, will invoke the specified loader. (babel-loader in this case) Furthermore, the exclude
regex tells webpack to ignore this special loader for all modules in the node_modules folder, this
helps speed up the transpilation process. Lastly, the query option tells webpack what parameters to
pass to babel and is used to pass along the presets we installed earlier.
All that is left now is to create the src/index.js file and try packing the application.
src/index.js:
Generated javascript
'use strict'
render(
<App />,
document.getElementById('app')
This file would normally render a simple <h1>Hello world!</h1> Header into the html tag with the
id 'app', but for now it should be enough to transpile the code once.
This should create the file out/bundle.js with the transpiled code inside and concludes the
example.
After setting up a simple project to use webpack, babel and react issuing $npm i -g
webpack-dev-server will install the development http server for quicker development.
Modifying webpack.config.js
Generated javascript
module.exports = {
entry: './src/index.js',
output: {
publicPath: '/public/',
filename: 'bundle.js'
},
module: {
loaders: [
test: /\.js$/,
exclude: /(node_modules)/,
loader: 'babel',
query: {
},
devServer: {
hot: true
};
● output.publicPath which sets up a path to have our bundle be served from (see Webpack
configuration files for more info)
● devServer
○ contentBase the base path to serve static files from (for example index.html)
○ hot sets the webpack-dev-server to hot reload when changes get made to files on
disk
●
And finally we just need a simple index.html to test our app in.
index.html:
Generated html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>React Sandbox</title>
</head>
<body>
<script src="public/bundle.js"></script>
</body>
</html>
With this setup running $webpack-dev-server should start a local http server on port 8080 and
upon connecting should render a page containing a <h1>Hello world!</h1>.
Chapter 30: Integrating React with a Spring Boot Backend
Section 30.1: Introduction and Strategy
Combining a Spring Boot backend with a React frontend is a powerful and popular choice for
building modern web applications. This stack leverages the strengths of both technologies: Spring
Boot provides a robust, scalable, and secure foundation for building REST APIs and handling
business logic, while React offers a dynamic, efficient, and component-based library for creating rich
user interfaces.
In this chapter, we will walk through the process of creating a full-stack application from scratch. The
strategy involves two main phases:
1. Development: We will run the Spring Boot backend and the React frontend on separate
servers. The Spring Boot application will serve the API (e.g., on port 8080), and the React
development server will serve the UI (e.g., on port 3000). To handle API requests from the UI
without running into Cross-Origin Resource Sharing (CORS) issues, we will configure a
proxy in the React application.
2. Production: For a production build, we will configure our build tool (Maven or Gradle) to
build the React application into static assets (HTML, CSS, JS). These static files will then be
bundled into the final .jar file, allowing the Spring Boot application to serve both the API
and the UI from a single, self-contained executable.
This approach provides the best of both worlds: a fast, hot-reloading development experience and a
simple, unified deployment model.
GreetingController.java:
Generated java
package com.example.reactandspring;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import java.util.Collections;
@RestController
@GetMapping("/api/greeting")
// This returns a JSON object: {"message": "Hello from the Spring Boot backend!"}
Explanation of Annotations:
1. Run your Spring Boot application. You can do this by running the main method in the
ReactAndSpringApplication.java file from your IDE, or by using the command line:
2. Generated bash
3. ./mvnw spring-boot:run
4. Use code with caution.Bash
5.
6. Once the application has started (typically on port 8080), open a terminal or a browser and
navigate to http://localhost:8080/api/greeting.
You should see the following JSON response, confirming that your API endpoint is working:
Generated json
1. Open a terminal and navigate to the root directory of your Spring Boot project
(react-and-spring).
2. Run the following command to create the React app. We will name it frontend to keep it
distinct.
3. Generated bash
4. npx create-react-app frontend
5. Use code with caution.Bash
6. This will create a frontend directory containing a standard React project structure.
Open the file frontend/src/App.js and replace its contents with the following:
frontend/src/App.js:
Generated javascript
import './App.css';
function App() {
useEffect(() => {
fetch('/api/greeting')
.then(response => {
if (!response.ok) {
return response.json();
})
.then(data => {
setMessage(data.message);
})
.catch(error => {
});
}, []); // The empty dependency array ensures this effect runs only once
return (
<div className="App">
<header className="App-header">
<p>
</p>
</header>
</div>
);
Explanation:
6.
Generated json
"name": "frontend",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:8080",
"dependencies": {
// ...
},
// ...
}
Use code with caution.Json
Now, whenever the React development server receives a request for a path it doesn't recognize (like
/api/greeting), it will forward that request to the backend server specified in the proxy.
1. Start the Backend: In one terminal, navigate to the root of the Spring Boot project
(react-and-spring) and start the server:
2. Generated bash
3. ./mvnw spring-boot:run
4. Use code with caution.Bash
5.
6. Start the Frontend: In a second terminal, navigate into the frontend directory and start the
React development server:
7. Generated bash
cd frontend
10.
Congratulations, you have successfully integrated a React frontend with a Spring Boot backend in a
development environment.
pom.xml:
Generated xml
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<configuration>
<workingDirectory>frontend</workingDirectory>
<installDirectory>target</installDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v16.15.0</nodeVersion>
<npmVersion>8.5.5</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>copy-react-build-to-static</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/static</outputDirectory>
<resources>
<resource>
<directory>frontend/build</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Explanation:
Now, you can create a single production-ready artifact by running the standard Maven package
command from the project root:
Generated bash
Generated bash
Navigate to http://localhost:8080 in your browser. You will see your React application being
served directly by Spring Boot, and it will correctly fetch its data from the API on the same origin.
Chapter 31: Deploying the Integrated Application
Section 31.1: Deployment Strategies Overview
Once you have successfully integrated your Spring Boot and React application and created a single,
executable .jar file, the next step is deployment. The self-contained nature of this artifact simplifies
the deployment process significantly. This chapter will explore several common and effective
strategies for deploying your application to a production environment.
1. Direct Deployment to a Virtual Private Server (VPS): The most straightforward method,
involving running the .jar file directly on a server.
2. Containerization with Docker: A modern, highly portable approach that packages your
application and its dependencies into a standardized unit (a container).
3. Deployment to Cloud Platforms (PaaS): Using Platform-as-a-Service providers like Heroku
or AWS Elastic Beanstalk, which abstract away much of the underlying infrastructure
management.
Each strategy has its own set of advantages and is suited for different scales and types of projects.
We will walk through the core concepts and steps for each.
First, create a new server instance from your chosen cloud provider. A basic Linux distribution like
Ubuntu 22.04 LTS is an excellent choice. Ensure you have SSH access to the server.
Your application needs a Java Runtime Environment (JRE) to run. Connect to your server via SSH
and install a compatible Java version. For our example using Java 17:
Generated bash
java -version
You need to copy the packaged .jar file from your local machine to the server. The scp (secure
copy) command is ideal for this. From your local machine's terminal, navigate to your project's root
and run:
Generated bash
Replace your_user and your_server_ip with your server's credentials. This command copies the
artifact to the home directory on the server and renames it to app.jar for simplicity.
Connect back to your server via SSH. You can now run the application:
Generated bash
java -jar ~/app.jar
Your application will start, but it will be tied to your current terminal session. If you log out, the
application will stop.
To ensure your application runs continuously and restarts automatically if the server reboots, it's best
to run it as a system service. We can use systemd, the standard service manager for most modern
Linux distributions.
5.
6. Add the following content to the file. Be sure to replace your_user with the actual
username you are using on the server.
7. Generated ini
[Unit]
After=syslog.target
[Service]
User=your_user
SuccessExitStatus=143
Restart=always
RestartSec=10
[Install]
8. WantedBy=multi-user.target
9. Use code with caution.Ini
10.Explanation:
○ ExecStart: The command to execute to start the service.
○ User: The user under which the process will run.
○ Restart=always: Tells systemd to automatically restart the service if it fails.
11.
12.Enable and start the service:
13.Generated bash
A Dockerfile is a text file that contains instructions for building a Docker image. Create a file
named Dockerfile (with no extension) in the root directory of your Spring Boot project.
Dockerfile:
Generated dockerfile
FROM openjdk:17-jdk-slim
WORKDIR /app
# The ARG is used to make the JAR file name dynamic, fetched from the build context
ARG JAR_FILE=target/react-and-spring-0.0.1-SNAPSHOT.jar
EXPOSE 8080
First, make sure you have Docker installed and running on your local machine.
1. Package the application: Before building the image, you need the .jar file. Run the Maven
package command if you haven't already:
2. Generated bash
3. ./mvnw clean package
4. Use code with caution.Bash
5.
6. Build the image: From the root of your project, run the docker build command. We will
tag the image with a name and version.
7. Generated bash
10.Replace your-dockerhub-username with your Docker Hub username (or any repository
name you prefer). The . at the end specifies that the build context is the current directory.
You can now run your application as a container on your local machine to test it:
Generated bash
This command starts a container from your image and maps port 8080 on your local machine to port
8080 inside the container. You can access your application at http://localhost:8080.
5.
6. On your production server: Install Docker, then pull and run the image.
7. Generated bash
# Run the container in detached mode (-d) and configure it to always restart
1. Install the Heroku CLI: Follow the official instructions to install it on your local machine.
2. Log in:
3. Generated bash
4. heroku login
5. Use code with caution.Bash
6.
7. Create a new app: Navigate to your project's root directory and run:
8. Generated bash
9. heroku create your-unique-app-name
10. Use code with caution.Bash
11. If you omit the name, Heroku will generate a random one for you. This command also adds a
new Git remote named heroku to your project.
Deploying to Heroku is as simple as pushing your code to the heroku Git remote.
git init
git add .
5.
6. Push to Heroku:
7. Generated bash
8. git push heroku main
9. Use code with caution.Bash
Once the deployment is complete, you can open your application in the browser:
Generated bash
heroku open
Heroku automatically exposes your application on port 80 (for HTTP) and 443 (for HTTPS), so you
don't need to specify a port number in the URL.