FSD Week 5
FSD Week 5
FSD Week 5
INTRODUCTION TO REACT
What is React ?
React is a declarative, efficient, and flexible JavaScript library for building user
interfaces. ReactJS is an open-source, component-based front-end library responsible
only for the view layer of the application. It is maintained by Facebook.
JB PORTALS 1
FULL STACK DEVELOPMENT - WEEK 5
Now after successfully installing the boilerplate the next thing we will do is create our
React app. We can use the create-react-app command for creating an app to React.
Run the below command to create a new project
:
You can run the project by typing the command cd my-app.
> cd my-app
> npm start
It will give you the output in the terminal as shown in the image below :
Now you can view your app in the browser as shown in the image below :
JB PORTALS 2
FULL STACK DEVELOPMENT - WEEK 5
In the above directory, you can see a number of files. The main files we will be
working on within the basic course are index.html and index.js. The index.html file will
have a div element with id = “root”, inside which everything will be rendered and all
of our React code will be inside the index.js file.
You can checkout the React.js docs for advanced setup.
JB PORTALS 3
FULL STACK DEVELOPMENT - WEEK 5
What is the Folder Structure for React Project?
The folder structure looks like this.
Assets Folder
Layouts Folder
Components Folder
Pages Folder
Middleware Folder
Routes Folder
Config Folder
Services Folder
Utils Folder
Assets Folder
As the name says, it contains assets of our project. It consists of images and
styling files. Here we can store our global styles. We are centralizing the project so we
can store the page-based or component-based styles over here. But we can even keep
style according to the pages folder or component folder also. But that depends on
developer comfortability.
Layouts Folder
As the name says, it contains layouts available to the whole project like header,
footer, etc. We can store the header, footer, or sidebar code here and call it.
JB PORTALS 4
FULL STACK DEVELOPMENT - WEEK 5
Components Folder
Components are the building blocks of any react project. This folder consists of
a collection of UI components like buttons, modals, inputs, loader, etc., that can be
used across various files in the project. Each component should consist of a test file
to do a unit test as it will be widely used in the project.
Pages Folder
The files in the pages folder indicate the route of the react application. Each file
in this folder contains its route. A page can contain its subfolder. Each page has its
state and is usually used to call an async operation. It usually consists of various
components grouped.
Middleware Folder
This folder consists of middleware that allows for side effects in the
application. It is used when we are using redux with it. Here we keep all our custom
middleware.
Routes Folder
This folder consists of all routes of the application. It consists of private,
protected, and all types of routes. Here we can even call our sub-route.
Config Folder
This folder consists of a configuration file where we store environment
variables in config.js. We will use this file to set up multi-environment configurations
in your application.
Services Folder
This folder will be added if we use redux in your project. Inside it, there are 3
folders named actions, reducers, and constant subfolders to manage states. The
actions and reducers will be called in almost all the pages, so create actions, reducers
& constants according to pages name.
Utils Folder
Utils folder consists of some repeatedly used functions that are commonly used
in the project. It should contain only common js functions & objects like dropdown
options, regex condition, data formatting, etc.
JB PORTALS 5
FULL STACK DEVELOPMENT - WEEK 5
C:\Users\username\Desktop\reactApp>npm init -y
Wrote to C:\reactApp\package.json:
{
"name": "reactApp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
JB PORTALS 6
FULL STACK DEVELOPMENT - WEEK 5
Step 2 - install React and react dom
Since our main task is to install ReactJS, install it, and its dom packages, using install
react and react-dom commands of npm respectively. You can add the packages we
install, to package.json file using the --save option.
C:\Users\Tutorialspoint\Desktop\reactApp>npm install react --save
C:\Users\Tutorialspoint\Desktop\reactApp>npm install react-dom --save
Or, you can install all of them in single command as −
C:\Users\username\Desktop\reactApp>npm install react react-dom --save
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './main.js',
output: {
path: path.join(__dirname, '/bundle'),
filename: 'index_bundle.js'
},
devServer: {
inline: true,
port: 8001
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
JB PORTALS 8
FULL STACK DEVELOPMENT - WEEK 5
query: {
presets: ['es2015', 'react']
}
}
]
},
plugins:[
new HtmlWebpackPlugin({
template: './index.html'
})
]
}
Open the package.json and delete "test" "echo \"Error: no test specified\"
&& exit 1" inside "scripts" object. We are deleting this line since we will not do any
testing in this tutorial. Let's add the start and build commands instead.
"start": "webpack-dev-server --mode development --open --hot",
"build": "webpack --mode production"
Step 7 - index.html
This is just regular HTML. We are setting div id = "app" as a root element for our app
and adding index_bundle.js script, which is our bundled app file.
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<title>React App</title>
</head>
<body>
<div id = "app"></div>
<script src = 'index_bundle.js'></script>
</body>
</html>
JB PORTALS 9
FULL STACK DEVELOPMENT - WEEK 5
Step 8 − App.jsx and main.js
This is the first React component. We will explain React components in depth
in a subsequent chapter. This component will render Hello World.
App.js
import React, { Component } from 'react';
class App extends Component{
render(){
return(
<div>
<h1>Hello World</h1>
</div>
);
}
}
export default App;
We need to import this component and render it to our root App element, so
we can see it in the browser.
main.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
Note − Whenever you want to use something, you need to import it first. If you want
to make the component usable in other parts of the app, you need to export it after
creation and import it in the file where you want to use it.
Create a file with name .babelrc and copy the following content to it.
{
"presets":["env", "react"]
}
JB PORTALS 10
FULL STACK DEVELOPMENT - WEEK 5
JB PORTALS 11
FULL STACK DEVELOPMENT - WEEK 5
JB PORTALS 12
FULL STACK DEVELOPMENT - WEEK 5
INTRODUCTION TO JSX
JSX stands for JavaScript XML. It is simply a syntax extension of JavaScript. It
allows us to directly write HTML in React (within JavaScript code). It is easy to
create a template using JSX in React, but it is not a simple template language instead
it comes with the full power of JavaScript. It is faster than normal JavaScript as it
performs optimizations while translating to regular JavaScript. Instead of
separating the markup and logic in separated files, React uses components for this
purpose. We will learn about components in detail in further articles.
Characteristics of JSX:
JSX is not mandatory to use there are other ways to achieve the same thing but
using JSX makes it easier to develop react application.
JSX allows writing expression in { }. The expression can be any JS expression or
React variable.
To insert a large block of HTML we have to write it in a parenthesis i.e, ().
JSX produces react elements.
JSX follows XML rule.
After compilation, JSX expressions become regular JavaScript function calls.
JSX uses camelcase notation for naming HTML attributes. For example, tabindex
in HTML is used as tabIndex in JSX.
Expressions in JSX
In React we are allowed to use normal JavaScript expressions with JSX. To embed any
JavaScript expression in a piece of code written in JSX we will have to wrap that
expression in curly braces {}. Consider the below program, written in the index.js file:
import React from 'react';
import ReactDOM from 'react-dom';
const name = "Learner";
const element = <h1>Hello,
{ name }.Welcome to React Course.< /h1>;
ReactDOM.render(
element,
document.getElementById("root")
);
JB PORTALS 13
FULL STACK DEVELOPMENT - WEEK 5
Output:
In the above program we have embedded the javascript expression const name
= “Learner”; in our JSX code. We embed the use of any JavaScript expression in JSX by
wrapping them in curly braces except if-else statements. But we can use conditional
statements instead of if-else statements in JSX. Below is the example where
conditional expressing is embedded in JSX:
let i = 1;
const element = <h1>{ (i == 1) ? 'Hello World!' : 'False!' } < /h1>;
ReactDOM.render(
element,
document.getElementById("root")
);
Output:
In the above example, the variable i is checked if for the value 1. As it equals 1
so the string ‘Hello World!’ is returned to the JSX code. If we modify the value of the
variable i then the string ‘False’ will be returned.
ReactDOM.render(
element,
document.getElementById("root")
);
1. As for string literals: We can specify the values of attributes as hard-coded strings
using quotes:
const ele = <h1 className = "firstAttribute">Hello!</h1>;
2. As expressions: We can specify attributes as expressions using curly braces {}:
const ele = <h1 className = {varName}>Hello!</h1>;
Rendering Elements
In order to render any element into the Browser DOM, we need to have a
container or root DOM element. It is almost a convention to have a div element with
the id=”root” or id=”app” to be used as the root DOM element. Let’s suppose our
index.html file has the following statement inside it.
<div id="root"></div>
Filename App.js: Now, in order to render a simple React Element to the root node,
we must write the following in the App.js file.
JB PORTALS 16
FULL STACK DEVELOPMENT - WEEK 5
DOM (Document Object Model)
DOM, abbreviated as Document Object Model, is a World Wide Web
Consortium standard logical representation of any webpage. In easier words, DOM is
a tree-like structure that contains all the elements and it’s properties of a website as
its nodes. DOM provides a language-neutral interface that allows accessing and
updating of the content of any element of a webpage.
React DOM
ReactDOM is a package that provides DOM specific methods that can be used at
the top level of a web app to enable an efficient way of managing DOM elements of
the web page. ReactDOM provides the developers with an API containing the
following methods and a few more.
render()
findDOMNode()
unmountComponentAtNode()
hydrate()
createPortal()
To use the ReactDOM in any React web app we must first import ReactDOM from
the react-dom package by using the following code snippet:
Import ReactDOM from ‘react-dom’;
render() Function
This is one of the most important methods of ReactDOM. This function is used
to render a single React Component or several Components wrapped together in a
Component or a div element. This function uses the efficient methods of React for
updating the DOM by being able to change only a subtree, efficient diff methods, etc.
Syntax:
ReactDOM.render(element, container, callback)
JB PORTALS 18
FULL STACK DEVELOPMENT - WEEK 5
class Democomponent extends React.Component
{
render(){
return <h1>Welcome Message!</h1>;
}
}
Rendering a Component
React is also capable of rendering user-defined components. To render a
component in React we can initialize an element with a user-defined component and
pass this element as the first parameter to ReactDOM.render() or directly pass the
component as the first argument to the ReactDOM.render() method. Below syntax
shows how to initialize a component to an element:
const elementName = <ComponentName />;
In the above syntax, the ComponentName is the name of the user-defined component.
Note: The name of a component should always start with a capital letter. This is done
to differentiate a component tag with html tags.
JB PORTALS 19
FULL STACK DEVELOPMENT - WEEK 5
2. React then calls the component Welcome, which returns <h1>Hello World!</h1>;
as the result.
3. Then the ReactDOM efficiently updates the DOM to match with the returned
element and renders that element to the DOM element with id as “root”.
Composing Components
This is the way of re-using the same user defined component again and again
for a specific purpose. In the below example, we are using Greeting component in
App.js file to render multiple times.
const Greeting = ()=>{
return <h1>Hello From React Greeting !</h1>;
}
export default function App() {
return (
<div>
<Greeting/>
<Greeting/>
<Greeting/>
</div>
); }
In the above example we are using Greeting component 3 times in App component.
Output:
2. Component name must be start with capital letter to differentiate between DOM
elements and user defined components.
JB PORTALS 20
FULL STACK DEVELOPMENT - WEEK 5
In the below example we are creating Button Componet with static label.
const Button = ()=>{
return <div>Button Label</div>;
}
You can render this Button by referring rendering of component method.In the below
example we are using this Button Component in App component to render it on
the DOM.
export default function App() {
return (
<div>
<Button/>
</div>
); }
Output:
JB PORTALS 21
FULL STACK DEVELOPMENT - WEEK 5
Firstly, we need to define/get some data from the parent component and assign it to
a child component’s “prop” attribute.
<ChildComponent name="First Child" />
“Name” is a defined prop here and contains text data. Then we can pass data with
props like we’re giving an argument to a function:
What is state?
React has another special built-in object called state, which allows components to
create and manage their own data. So unlike props, components cannot pass data
with state, but they can create and manage it internally.
Here is an example showing how to use state:
class Test extends React.Component {
constructor() {
this.state = {
id: 1,
name: "test"
};
}
render() {
return (
<div>
<p>{this.state.id}</p>
<p>{this.state.name}</p>
</div>
);
}
}
JB PORTALS 22
FULL STACK DEVELOPMENT - WEEK 5
How do you update a component’s state?
State should not be modified directly, but it can be modified with a special
method called setState( ).
this.state.id = “2020”; // wrong
this.setState({ // correct
id: "2020"});
What happens when state changes?
OK, why must we use setState( )? Why do we even need the state object itself?
If you’re asking these questions, don't worry – you’ll understand state soon :) Let me
answer.
So when state changes, React gets informed and immediately re-renders the
DOM – not the whole DOM, but only the component with the updated state. This
is one of the reasons why React is fast.
And how does React get notified? You guessed it: with setState( ). The setState(
) method triggers the re-rendering process for the updated parts. React gets
informed, knows which part(s) to change, and does it quickly without re-rendering
the whole DOM.
JB PORTALS 23
FULL STACK DEVELOPMENT - WEEK 5
Communication between components using props
React is a component-based UI library. When the UI is split into small, focused
components, they can do one job and do it well. But in order to build up a system into
something that can accomplish an interesting task, multiple components are needed.
These components often need to work in coordination together and, thus, must be
able to communicate with each other. Data must flow between them.
React components are composed in a hierarchy that mimics the DOM tree
hierarchy that they are used to create. There are those components that are higher
(parents) and those components that are lower (children) in the hierarchy. Let's take
a look at the directional communication and data flow that React enables between
components.
function BookList() {
const list = [
{ title: 'A Christmas Carol', author: 'Charles Dickens' },
{ title: 'The Mansion', author: 'Henry Van Dyke' },
// ...
]
return (
<ul>
{list.map((book, i) => <Book title={book.title} author={book.author}
key={i} />)}
</ul>
)
}
Then the Book component can receive and use those fields as contained in
the props parameter to its function:
JB PORTALS 24
FULL STACK DEVELOPMENT - WEEK 5
function Book(props) {
return (
<li>
<h2>{props.title</h2>
<div>{props.author}</div>
</li>
)
}
function BookTitle(props) {
return (
<label>
Title:
<input onChange={props.onTitleChange} value={props.title} />
</label>
)
}
It receives a onTitleChange function in the props, sent from its parent. It binds
this function to the onChange event on the <input /> field. When the input changes, it
will call the onTitleChange callback, passing the change Event object. Because the
parent, BookEditForm, has reference to this function, it can receive the arguments
that are passed to the function:
function BookEditForm(props) {
const [title, setTitle] = useState(props.book.title)
function handleTitleChange(evt) {
setTitle(evt.target.value)
}
JB PORTALS 25
FULL STACK DEVELOPMENT - WEEK 5
return (
<form>
<BookTitle onTitleChange={handleTitleChange} title={title} />
</form>
)
}
In this case, the parent passed handleTitleChange, and when it's called, it sets
the internal state based on the value of evt.target.value -- a value that has come as a
callback argument from the child component. There are some cases, however, when
data sent through props might not be the best option for communicating between
components. For these cases, React provides a mechanism called context.
function BookPage() {
return (
<ThemeContext.Provider value="light">
<BookList />
</ThemeContext.Provider>
)
}
The ThemeContext need only be created once and, thus, is created outside the
component function. It is given a default of "dark" as a fallback theme name. The
context object contains a Provider function which we wrap our rendered child
component in. We can specify a value to override the default theme. Here, we are
saying our BookPage will always show the "light" theme. Note also that BookList does
not receive any theme props. We can leave its implementation as-is. But let's say that
we want our Book component to respond to theming. We could adjust it to something
like:
JB PORTALS 26
FULL STACK DEVELOPMENT - WEEK 5
import React, { useContext } from 'react'
function Book(props) {
const theme = useContext(ThemeContext)
const styles = {
dark: { background: 'black', color: 'white' },
light: { background: 'white', color: 'black' }
}
return (
<li style={styles[theme]}>
<h2>{props.title</h2>
<div>{props.author}</div>
</li>
)
}
Initialization: This is the stage where the component is constructed with the
given Props and default state. This is done in the constructor of a Component
Class.
Mounting: Mounting is the stage of rendering the JSX returned by the render
method itself.
Updating: Updating is the stage when the state of a component is updated and
the application is repainted.
Unmounting: As the name suggests Unmounting is the final step of the
component lifecycle where the component is removed from the page.
JB PORTALS 27
FULL STACK DEVELOPMENT - WEEK 5
React provides the developers a set of predefined functions that if present is
invoked around specific events in the lifetime of the component. Developers are
supposed to override the functions with desired logic to execute accordingly. We
have illustrated the gist in the following diagram.
JB PORTALS 28
FULL STACK DEVELOPMENT - WEEK 5
The mounting phase consists of two such predefined functions as described below.
render() Function: The render() method is the only required method in a class
component.
When called, it should examine this.props and this.state and return one of the
following types:
React elements. Typically created via JSX. For example, <div /> and <MyComponent
/> are React elements that instruct React to render a DOM node, or another user-
defined component, respectively.
Arrays and fragments. Let you return multiple elements from render. See the
documentation on fragments for more details.
Portals. Let you render children into a different DOM subtree. See the documentation
on portals for more details.
String and numbers. These are rendered as text nodes in the DOM.
Booleans or null or undefined. Render nothing. (Mostly exists to support return test
&& <Child /> pattern, where test is boolean).
The render() function should be pure, meaning that it does not modify
component state, it returns the same result each time it’s invoked, and it does not
directly interact with the browser.
3. Updation:
React is a JS library that helps create Active web pages easily. Now active web
pages are specific pages that behave according to their user. For example, let’s take
the GeeksforGeeks {IDE} webpage, the webpage acts differently with each user. User
A might write some code in C in the Light Theme while another User may write a
Python code in the Dark Theme all at the same time.
JB PORTALS 29
FULL STACK DEVELOPMENT - WEEK 5
This dynamic behavior that partially depends upon the user itself makes the
webpage an Active webpage. Now how can this be related to Updation? Updation is
the phase where the states and props of a component are updated followed by some
user events such as clicking, pressing a key on the keyboard, etc.
The following are the descriptions of functions that are invoked at different
points of Updation phase.
We have so far discussed every predefined function there was in the lifecycle of
the component, and we have also specified the order of execution of the function.
Let us now see one final example to finish the article while revising what’s discussed
above.
First, create a react app and edit your index.js file from the src folder.
src index.js:
import React from 'react';
import ReactDOM from 'react-dom';
componentWillMount()
{
console.log("componentWillMount()");
}
componentDidMount()
{
console.log("componentDidMount()");
}
changeState()
{
this.setState({ hello : "Geek!" });
}
render()
{
JB PORTALS 31
FULL STACK DEVELOPMENT - WEEK 5
return (
<div>
<h1>GeeksForGeeks.org, Hello{ this.state.hello }</h1>
<h2>
<a onClick={this.changeState.bind(this)}>Press Here!</a>
</h2>
</div>);
}
shouldComponentUpdate(nextProps, nextState)
{
console.log("shouldComponentUpdate()");
return true;
}
componentWillUpdate()
{
console.log("componentWillUpdate()");
}
componentDidUpdate()
{
console.log("componentDidUpdate()");
}
}
ReactDOM.render(
<Test />,
document.getElementById('root'));
Output:
JB PORTALS 32
FULL STACK DEVELOPMENT - WEEK 5
4. Error Handling
There are two main methods in error handling. These method are used in the error
boundary mechanism in React. We wrap the component (from where there is a
possibility of error occurrences ) in a class which handles the below methods.
componentDidCatch(error, info): we can log the errors using api call. This is
helpful in displaying useful error message on screen instead of technical errors.
If error is not cached by error boundary class then the entire react component
tree below that component will be removed.
We can use the try catch in some methods but in application wide using error
boundary is better standard. It keeps the declarative nature of react intact.
Handling Events
REFERENCE LINK: https://reactjs.org/docs/handling-events.html
Handling events with React elements is very similar to handling events on DOM
elements. There are some syntax differences:
JB PORTALS 33
FULL STACK DEVELOPMENT - WEEK 5
Another difference is that you cannot return false to prevent default behavior
in React. You must call preventDefault explicitly. For example, with plain HTML, to
prevent the default form behavior of submitting, you can write:
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}
When using React, you generally don’t need to call addEventListener to add
listeners to a DOM element after it is created. Instead, just provide a listener when the
element is initially rendered.
When you define a component using an ES6 class, a common pattern is for an
event handler to be a method on the class. For example, this Toggle component
renders a button that lets the user toggle between “ON” and “OFF” states:
You have to be careful about the meaning of this in JSX callbacks. In JavaScript,
class methods are not bound by default. If you forget to bind this.handleClick and pass
it to onClick, this will be undefined when the function is actually called. This is not
React-specific behavior; it is a part of how functions work in JavaScript. Generally, if
you refer to a method without () after it, such as onClick={this.handleClick}, you
should bind that method.
If calling bind annoys you, there are two ways you can get around this. You can
use public class fields syntax to correctly bind callbacks:
This syntax is enabled by default in Create React App. If you aren’t using class
fields syntax, you can use an arrow function in the callback:
render() {
// This syntax ensures `this` is bound within handleClick return (
<button onClick={() => this.handleClick()}> Click me
</button>
);
}
}
JB PORTALS 35
FULL STACK DEVELOPMENT - WEEK 5
Passing Arguments to Event Handlers
Inside a loop, it is common to want to pass an extra parameter to an event
handler. For example, if id is the row ID, either of the following would work:
Conditional Rendering
REFERENCE LINK: https://reactjs.org/docs/conditional-rendering.html
In React, you can create distinct components that encapsulate behavior you
need. Then, you can render only some of them, depending on the state of your
application.
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) { return <UserGreeting />; } return <GuestGreeting />;}
const root = ReactDOM.createRoot(document.getElementById('root'));
// Try changing to isLoggedIn={true}:
root.render(<Greeting isLoggedIn={false} />);
JB PORTALS 36
FULL STACK DEVELOPMENT - WEEK 5
Element Variables
You can use variables to store elements. This can help you conditionally render
a part of the component while the rest of the output doesn’t change.Consider these
two new components representing Logout and Login buttons:
function LoginButton(props) {
return (
<button onClick={props.onClick}>
Login
</button>
);
}
function LogoutButton(props) {
return (
<button onClick={props.onClick}>
Logout
</button>
);
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
JB PORTALS 37
FULL STACK DEVELOPMENT - WEEK 5
if (isLoggedIn) { button = <LogoutButton
onClick={this.handleLogoutClick} />; } else { button = <LoginButton
onClick={this.handleLoginClick} />; }
return (
<div>
<Greeting isLoggedIn={isLoggedIn} /> {button} </div>
);
}
}
You may embed expressions in JSX by wrapping them in curly braces. This
includes the JavaScript logical && operator. It can be handy for conditionally
including an element:
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 && <h2> You have
{unreadMessages.length} unread messages. </h2> } </div>
);
}
JB PORTALS 38
FULL STACK DEVELOPMENT - WEEK 5
Note that returning a falsy expression will still cause the element after && to
be skipped but will return the falsy expression. In the example
below, <div>0</div> will be returned by the render method.
render() {
const count = 0; return (
<div>
{count && <h1>Messages: {count}</h1>} </div>
);
}
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in. </div>
);
}
It can also be used for larger expressions although it is less obvious what’s
going on:
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn ? <LogoutButton onClick={this.handleLogoutClick} />
: <LoginButton onClick={this.handleLoginClick} /> }
</div> );
}
JB PORTALS 39
FULL STACK DEVELOPMENT - WEEK 5
In the example below, the <WarningBanner /> is rendered depending on the
value of the prop called warn. If the value of the prop is false, then the component
does not render:
function WarningBanner(props) {
if (!props.warn) { return null; }
return (
<div className="warning">
Warning!
</div>
);
}
handleToggleClick() {
this.setState(state => ({
showWarning: !state.showWarning
}));
}
render() {
return (
<div>
<WarningBanner warn={this.state.showWarning} /> <button
onClick={this.handleToggleClick}>
{this.state.showWarning ? 'Hide' : 'Show'}
</button>
</div>
);
}
}
Returning null from a component’s render method does not affect the firing of
the component’s lifecycle methods. For instance componentDidUpdate will still be
called.
JB PORTALS 40
FULL STACK DEVELOPMENT - WEEK 5
Lists and Keys
REFERENCE LINK: https://reactjs.org/docs/lists-and-keys.html
This code logs [2, 4, 6, 8, 10] to the console. In React, transforming arrays into lists
of elements is nearly identical.
Then, we can include the entire listItems array inside a <ul> element:
<ul>{listItems}</ul>
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) => <li>{number}</li> ); return
(
<ul>{listItems}</ul> );
}
Let’s assign a key to our list items inside numbers.map() and fix the missing
key issue.
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}> {number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
Keys
Keys help React identify which items have changed, are added, or are removed.
Keys should be given to the elements inside the array to give the elements a stable
identity:
The best way to pick a key is to use a string that uniquely identifies a list item
among its siblings. Most often you would use IDs from your data as keys:
When you don’t have stable IDs for rendered items, you may use the item index
as a key as a last resort:
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Wrong! The key should have been specified here: <ListItem
value={number} /> );
return (
<ul>
{listItems}
</ul>
);
}
function ListItem(props) {
// Correct! There is no need to specify the key here: return
<li>{props.value}</li>;}
function NumberList(props) {
const numbers = props.numbers;
JB PORTALS 43
FULL STACK DEVELOPMENT - WEEK 5
const listItems = numbers.map((number) =>
// Correct! Key should be specified inside the array. <ListItem
key={number.toString()} value={number} /> );
return (
<ul>
{listItems}
</ul>
);
}
A good rule of thumb is that elements inside the map() call need keys. Keys
Must Only Be Unique Among Siblings. Keys used within arrays should be unique
among their siblings. However, they don’t need to be globally unique. We can use the
same keys when we produce two different arrays:
function Blog(props) {
const sidebar = ( <ul>
{props.posts.map((post) =>
<li key={post.id}> {post.title}
</li>
)}
</ul>
);
const content = props.posts.map((post) => <div key={post.id}>
<h3>{post.title}</h3>
<p>{post.content}</p>
</div>
);
return (
<div>
{sidebar} <hr />
{content} </div>
);
}
const posts = [
{id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
{id: 2, title: 'Installation', content: 'You can install React from npm.'}
];
JB PORTALS 44
FULL STACK DEVELOPMENT - WEEK 5
Keys serve as a hint to React but they don’t get passed to your components. If
you need the same value in your component, pass it explicitly as a prop with a
different name:
const content = posts.map((post) =>
<Post
key={post.id} id={post.id} title={post.title} />
);
With the example above, the Post component can read props.id, but
not props.key.
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) => <ListItem
key={number.toString()} value={number} /> ); return (
<ul>
{listItems}
</ul>
);
}
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) => <ListItem key={number.toString()}
value={number} /> )} </ul>
);
}
Sometimes this results in clearer code, but this style can also be abused. Like
in JavaScript, it is up to you to decide whether it is worth extracting a variable for
readability. Keep in mind that if the map() body is too nested, it might be a good time
to extract a component.
JB PORTALS 45
FULL STACK DEVELOPMENT - WEEK 5
Forms
REFERENCE LINK: https://reactjs.org/docs/forms.html
HTML form elements work a bit differently from other DOM elements in React,
because form elements naturally keep some internal state. For example, this form in
plain HTML accepts a single name:
<form>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>
This form has the default HTML form behavior of browsing to a new page when
the user submits the form. If you want this behavior in React, it just works. But in most
cases, it’s convenient to have a JavaScript function that handles the submission of the
form and has access to the data that the user entered into the form. The standard way
to achieve this is with a technique called “controlled components”.
Controlled Components
In HTML, form elements such as <input>, <textarea>, and <select> typically
maintain their own state and update it based on user input. In React, mutable state is
typically kept in the state property of components, and only updated with setState().
We can combine the two by making the React state be the “single source of
truth”. Then the React component that renders a form also controls what happens in
that form on subsequent user input. An input form element whose value is controlled
by React in this way is called a “controlled component”.
For example, if we want to make the previous example log the name when it is
submitted, we can write the form as a controlled component:
render() {
return (
<form onSubmit={this.handleSubmit}> <label>
Name:
<input type="text" value={this.state.value}
onChange={this.handleChange} /> </label>
<input type="submit" value="Submit" />
</form>
);
}
}
Since the value attribute is set on our form element, the displayed value will
always be this.state.value, making the React state the source of truth.
Since handleChange runs on every keystroke to update the React state, the displayed
value will update as the user types.
With a controlled component, the input’s value is always driven by the React
state. While this means you have to type a bit more code, you can now pass the value
to other UI elements too, or reset it from other event handlers.
<textarea>
Hello there, this is some text in a text area
</textarea>
In React, a <textarea> uses a value attribute instead. This way, a form using
a <textarea> can be written very similarly to a form that uses a single-line input:
JB PORTALS 47
FULL STACK DEVELOPMENT - WEEK 5
handleChange(event) { this.setState({value: event.target.value}); }
handleSubmit(event) {
alert('An essay was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Essay:
<textarea value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
Notice that this.state.value is initialized in the constructor, so that the text area
starts off with some text in it.
<select>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option selected value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
JB PORTALS 48
FULL STACK DEVELOPMENT - WEEK 5
class FlavorForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'coconut'};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Pick your favorite flavor:
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
Overall, this makes it so that <input type="text">, <textarea>, and <select> all
work very similarly - they all accept a value attribute that you can use to implement
a controlled component.
Note
You can pass an array into the value attribute, allowing you to select multiple options
in a select tag:
JB PORTALS 49
FULL STACK DEVELOPMENT - WEEK 5
The file input Tag
In HTML, an <input type="file"> lets the user choose one or more files from
their device storage to be uploaded to a server or manipulated by JavaScript via
the File API.
For example:
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value });
}
render() {
return (
<form>
<label>
Is going:
<input
name="isGoing" type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
JB PORTALS 50
FULL STACK DEVELOPMENT - WEEK 5
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests" type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}
Note how we used the ES6 computed property name syntax to update the state
key corresponding to the given input name:
this.setState({
[name]: value});
Also, since setState() automatically merges a partial state into the current state,
we only needed to call it with the changed parts.
Uncontrolled Components
In most cases, we recommend using controlled components to implement
forms. In a controlled component, form data is handled by a React component. The
alternative is uncontrolled components, where form data is handled by the DOM
itself.
JB PORTALS 51
FULL STACK DEVELOPMENT - WEEK 5
handleSubmit(event) {
alert('A name was submitted: ' + this.input.current.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" ref={this.input} /> </label>
<input type="submit" value="Submit" />
</form>
);
}
}
Default Values
In the React rendering lifecycle, the value attribute on form elements will
override the value in the DOM. With an uncontrolled component, you often want
React to specify the initial value, but leave subsequent updates uncontrolled. To
handle this case, you can specify a defaultValue attribute instead of value. Changing
the value of defaultValue attribute after a component has mounted will not cause any
update of the value in the DOM.
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input
defaultValue="Bob" type="text"
ref={this.input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
JB PORTALS 52
FULL STACK DEVELOPMENT - WEEK 5
Likewise,
<input type="checkbox"> and <input type="radio"> support defaultChecked,
and <select> and <textarea> supports defaultValue.
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Upload file:
<input type="file" ref={this.fileInput} /> </label>
<br />
<button type="submit">Submit</button>
</form>
);
}
}
JB PORTALS 53
FULL STACK DEVELOPMENT - WEEK 5
Lifting State up in ReactJS
REFERENCE LINK: https://reactjs.org/docs/lifting-state-up.html
https://www.geeksforgeeks.org/lifting-state-up-in-reactjs/
Lifting up the State: As we know, every component in React has its own state.
Because of this sometimes data can be redundant and inconsistent. So, by Lifting up
the state we make the state of the parent component as a single source of truth and
pass the data of the parent in its children.
Time to use Lift up the State: If the data in “parent and children components” or
in “cousin components” is Not in Sync.
Problem: Let’s Implement this with a simple but general example. We are
considering the second example.
Complete File Structure:
JB PORTALS 54
FULL STACK DEVELOPMENT - WEEK 5
We will store the current input’s temperature and scale in its local state. This
is the state we “lifted up” from the inputs, and it will serve as the “source of truth” for
both of them. It is the minimal representation of all the data we need to know in order
to render both inputs.
{
temperature: '37',
scale: 'c'
}
If we later edit the Fahrenheit field to be 212, the state of the Calculator will be:
{
temperature: '212',
scale: 'f'
}
const scaleNames = {
c: 'Celsius',
f: 'Fahrenheit'
};
function toCelsius(fahrenheit) {
return (fahrenheit - 32) * 5 / 9;
}
function toFahrenheit(celsius) {
return (celsius * 9 / 5) + 32;
}
JB PORTALS 55
FULL STACK DEVELOPMENT - WEEK 5
function BoilingVerdict(props) {
if (props.celsius >= 100) {
return <p>The water would boil.</p>;
}
return <p>The water would not boil.</p>;
}
handleChange(e) {
this.props.onTemperatureChange(e.target.value);
}
render() {
const temperature = this.props.temperature;
const scale = this.props.scale;
return (
<fieldset>
<legend>Enter temperature in {scaleNames[scale]}:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
JB PORTALS 56
FULL STACK DEVELOPMENT - WEEK 5
handleCelsiusChange(temperature) {
this.setState({scale: 'c', temperature});
}
handleFahrenheitChange(temperature) {
this.setState({scale: 'f', temperature});
}
render() {
const scale = this.state.scale;
const temperature = this.state.temperature;
const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) :
temperature;
const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) :
temperature;
return (
<div>
<TemperatureInput
scale="c"
temperature={celsius}
onTemperatureChange={this.handleCelsiusChange} />
<TemperatureInput
scale="f"
temperature={fahrenheit}
onTemperatureChange={this.handleFahrenheitChange} />
<BoilingVerdict
celsius={parseFloat(celsius)} />
</div>
);
}
}
JB PORTALS 57
FULL STACK DEVELOPMENT - WEEK 5
Testing Single Page Applications
REFERENCE LINK: https://medium.com/inspiredbrilliance/testing-single-page-
applications-b4001adc6452
There are many ways to test the frontend of a web application. Most widely
used methods are to test the application as a user using Selenium Web-driver or
similar libraries. This means that you have to write tests for each and every scenario
as a user workflow.
This made our testing slow and delayed the whole Test Driven Development
cycle. That leads to most UI developers to only write application code and let the UI
Automation teams write tests for them. It is not difficult to see then that the
dependency on multiple teams delayed the feedback cycle. Thus delaying the
continuous delivery process.
But today we are mainly going to focus on testing Single Page Applications
(SPA). Modern SPA frameworks like React, Angular and Vue.js use component based
approach to build UI by composing smaller components together. This provides us an
opportunity to test our application logic at component level as well as the complete
app as a black box.
Because of this granularity of modern SPA testing our testing pyramid would
usually look like following:
JB PORTALS 58
FULL STACK DEVELOPMENT - WEEK 5
1. Unit Tests:
These are your tests for plain old Javascript functions and classes that you are
writing as part of the application. These may include any domain classes, functional
utilities or more specifically the helper functions of the UI components. Because these
tests usually don’t depend on any other code or library you should be able to write
tests for each and every use case of these functions. There are many frameworks
available in Javascript to test this kind of Javascript objects. Most commonly used
are Jasmine, Mocha and Jest.
After testing all our components in isolation of groups we still need to make
sure that our app works end to end without stubbing any of its components. The goal
of end to end (e2e) tests is to test our app as a user. We can not assume any internals
of the applications. We should treat it as a complete black box and assert the behaviour
completely on the outcome of user actions.
There are many ways to execute e2e tests in browser, for example
using Selenium Web Driver, Puppeteer, TestCafe or Cypress
JB PORTALS 59