React Js Material
React Js Material
Concepts in Focus
• React JS
• Why React JS?
• Advantages of React JS
• Running JavaSript in HTML
• Creating Elements using React JS
• React CDN
• React.createElement()
• ReactDOM.render()
• JSX
• Babel
• Embedding Variables and Expressions in JSX
• Nesting JSX elements
1. React JS
React JS is an open-source JavaScript library used to build user interfaces. It was developed by
Facebook.
<body>
<div id="root"></div>
<script type="text/javascript">
Venkatesh Athyam
Note:
When the browser comes across a script element while loading the HTML, it
must wait for the script to download, execute it, and only then can it process
the rest of the page.
So, we need to put a script element at the bottom of the page. Then the
browser can see elements above it and doesn’t block the page content from
showing.
If more than one script elements are in the HTML, the script elements will be
executed in the order they appear.
3.2 React.createElement()
The React.createElement() method is used to create an element using React JS. It is similar to the
document.createElement() method in regular JavaScript.
Syntax:
React.createElement(type, props);
<script type="module">
Venkatesh Athyam
Note:
The type attribute value of the HTML script element should be module to ru
React JS.
3.3 ReactDOM.render()
The ReactDOM.render() method is used to display the React element.
Syntax:
ReactDOM.render(reactElement, container);
<body>
<div id="root"></div>
<script type="module">
const elementProps = { className: "greeting", children: "Hello world!" };
const elementType = "h1";
const element = React.createElement(elementType, elementProps);
ReactDOM.render(element, document.getElementById("root"));
</script>
</body>
4. JSX
React JS introduced a new HTML like syntax named JSX to create elements.
const element = <h1 className="greeting">Hello World</h1>;
The above JSX element compiles to,
const elementProps = { className: "greeting", children: "Hello world!" };
const element = React.createElement("h1", elementProps);
Warning:
In JSX, HTML tags always need to be closed. For example, <br />, <img />.
4.1 Babel
JSX is not JavaScript. We have to convert it to JavaScript using a code compiler. Babel is one such
tool.
It is a JavaScript compiler that translates JSX into regular JavaScript.
Venkatesh Athyam
<script type="text/babel">
const elementProps = { className: "greeting", children: "Hello world!" };
const element = React.createElement("h1", elementProps);
const element = <h1 className="greeting">Hello World</h1>;
ReactDOM.render(element, document.getElementById("root"));
</script>
Note:
For JSX, the type attribute value of the HTML script element should be text/babel
For providing class names in JSX, the attribute name should be className
Differences between HTML and JSX:
HTML JSX
class className
for htmlFor
<body>
<div id="root"></div>
<script type="text/babel">
const fullName = (user) => user.firstName + " " + user.lastName;
const user = { firstName: "Rahul ", lastName: "Attuluri" };
const element = <h1 className="greeting"> Hello, {fullName(user)}!</h1>;
ReactDOM.render(element, document.getElementById("root"));
</script>
</body>
<body>
<script type="text/babel">
const element = (
<div>
<h1 className="greeting">Hello!</h1>
<p>Good to see you here.</p>
</div>
);
ReactDOM.render(element, document.getElementById("root"));
</script>
</body>
Concepts in Focus
• Component
• Properties (Props)
• Component is Reusable
• Component is Composable
• Third-party Packages
• create-react-app
• Pre-Configured tools
1. Component
A Component is a JS function that returns a JSX element.
Venkatesh Athyam
ReactDOM.render(
Venkatesh Athyam
ReactDOM.render(
<div>
<Welcome name="Rahul" greeting="Hello" />
<Welcome name="Ram" greeting="Hi" />
</div>,
document.getElementById("root")
);
};
const Greetings = () => (
<div>
<Welcome name="Rahul" greeting="Hello" />
<Welcome name="Ram" greeting="Hi" />
</div>
);
2. Third-party Packages
Creating a real-world app involves lot of setup because a large number of components need to be
organised.
Facebook has created a third-party package,
create-react-app
, to generate a ready-made React application setup.
2.1 create-react-app
Installation Command:
npm install -g create-react-app
It installs create-react-app globally in our environment.
The index.js in the path src/folder/ is a starting point to the application. App.js, App.css are
imported in this file.
2.1.3 Starting a React Application
Run the below command from the React application directory.
npm start
Note:
All the ES6 Modules should be named with .js extension.
1. Keys
Keys help React to identify which items have changed, added, or removed. They should be given to
the elements inside the array for 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, we would use IDs (uniqueNo) from our data as keys.
Example:
const userDetails = [
{
uniqueNo: 1,
imageUrl:
'https://assets.ccbp.in/frontend/react-js/esther-howard-img.png',
name: 'Esther Howard',
role: 'Software Developer'
}
]
Venkatesh Athyam
File: src/App.js
The index.js file in the folder is considered to be the main file in it. So, a path like
./components/UserProfile can be used instead of ./components/UserProfile/index
Note:
Venkatesh Athyam
Keys used within arrays should be unique among their siblings. However, they don't need to be
unique in the entire application.
return (
<li className="user-card-container">
<img src={imageUrl} className="avatar" alt="avatar" />
<div className="user-details-container">
<h1 className="user-name"> {name} </h1>
<p className="user-designation"> {role} </p>
</div>
</li>
)
}
export default UserProfile
If we need the same value in the component, pass it explicitly as a prop with a different name.
Example:
'https://assets.ccbp.in/frontend/react-js/esther-howard-img.png',
name: 'Esther Howard',
role: 'Software Developer'
},
{
uniqueNo: 2,
imageUrl:
'https://assets.ccbp.in/frontend/react-js/floyd-miles-img.png',
name: 'Floyd Miles',
role: 'Software Developer'
},
{
uniqueNo: 3,
imageUrl:
'https://assets.ccbp.in/frontend/react-js/jacob-jones-img.png',
name: 'Jacob Jones',
role: 'Software Developer'
},
{
uniqueNo: 4,
imageUrl:
'https://assets.ccbp.in/frontend/react-js/esther-devon-lane.png',
name: 'Devon Lane',
role: 'Software Developer'
}
]
return (
<li className="user-card-container">
<img src={imageUrl} className="avatar" alt="avatar" />
<div className="user-details-container">
<h1 className="user-name"> {name} </h1>
<p className="user-designation"> {role} </p>
</div>
</li>
)
}
export default UserProfile.
Note:
React Error - ENOSPC: System limit for the number of file watchers reached
Since create-react-app live-reloads and recompiles files on save, it needs to keep track of all
project files.
To fix the error, run the below commands in the terminal:
1. Insert the new value into the system config
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
2. Check that the new value was applied
Venkatesh Athyam
cat /proc/sys/fs/inotify/max_user_watches
3. Config variable name (not runnable)
fs.inotify.max_user_watches=524288
Concepts in Focus
• Components
• Functional Components
• Class Components
• React Events
• State
• Updating State
• State Updates are Merged
• Functional Components vs Class Components
• Counter Application
1. Components
There are two ways to write React Components.
They are:
• Functional Components
• Class Components
1.2.1 extends
The extends keyword is used to inherit methods and properties from the React.Component
.
Venkatesh Athyam
1.2.2 render()
The render() method is the only required method in a class component. It returns the JSX element.
Syntax:
2. React Events
Handling events with React elements is very similar to handling events on DOM elements. There
are some syntax differences:
1. React events are named using camelCase, rather than lowercase.
Example:
HTML JSX
onclick onClick
onblur onBlur
onchange onChange
2. With JSX, you pass a function as the event handler rather than a string.
Example:
<button onclick="activateLasers()">Activate Lasers</button>
<button onClick={activateLasers}>Activate Lasers</button>
In the above function, the handleClick is passed as a reference. So, the function is not being
called every time the component renders.
3. State
The state is a JS object in which we store the component's data that changes over time.
When the state object changes, the component re-renders.
Intialising State:
onIncrement = () => {
this.setState((prevState) =>
console.log(`previous state value ${prevState.count}`)
)
}
Use Class Components whenever the state is required. Otherwise, use the Functional components.
4. Counter Application
File: src/App.js
File: src/components/Counter/index.js
import "./index.css"
)
}
}
Conditional Rendering:
Concepts in Focus
• Conditional Rendering
• Using an If...Else Statement
• Using Element Variables
• Using Ternary Operators
• Using Logical && Operator
• Default Props
1 . Conditional Rendering
Conditional Rendering allows us to render different elements or components based on a condition.
Different ways to implement Conditional Rendering are:
• Using an If...Else Statement
• Using Element Variables
• Using Ternary Operators
• Using Logical && Operator
renderAuthButton = () => {
const {isLoggedIn} = this.state
if (isLoggedIn === true) {
return <button>Logout</button>
}
return <button>Login</button>
}
render() {
return (
<div className="container">
Venkatesh Athyam
{this.renderAuthButton()}
</div>
)
}
}
render() {
const { isLoggedIn } = this.state
let authButton
if (isLoggedIn) {
authButton = <button>Logout</button>
} else {
authButton = <button>Login</button>
}
return (
<div className="container">
<h1>React JS</h1>
{authButton}
</div>
)
}
}
Venkatesh Athyam
render() {
const { isLoggedIn } = this.state
return (
<div className="container">
{isLoggedIn ? <button>Logout</button> : <button>Login</button>}
</div>
)
}
}
render() {
const { isLoggedIn } = this.state
return (
<div className="container">
{isLoggedIn && <button>Logout</button>}
{!isLoggedIn && <button>Login</button>}
</div>
)
Venkatesh Athyam
}
}
2. Default Props
defaultProps is a property in React Component used to set default values for the props. This is
similar to adding default parameters to the function.
Syntax:
// Component Definition
ComponentName.defaultProps = {
propName1: "propValue1",
propName2: "propValue2"
}
// Exporting Component
Example:
File: src/Welcome/index.js
Welcome.defaultProps = {
name: "Rahul",
greeting: "Hello"
};
Concepts in Focus
• setState()
Object Syntax
Venkatesh Athyam
this.setState(
{propertyName1: propertyValue1},
{propertyName2: propertyValue2}
// and many more...
);
this.setState(prevState => {
return { count: prevState.count + 1 };
});
It is used while updating the state to a value, which is computed based on the
previous state.
Object:
this.setState({ quantity: 2 });
It is used while updating the state to a static value.
3. Input Element
In React, the Input Element
value
can be handled in two ways:
Venkatesh Athyam
• Controlled Input
• Uncontrolled Input
render() {
const {searchInput} = this.state
return (
<input
type="text"
onChange={this.onChangeSearchInput}
value={searchInput}
/>
)
}
}
Venkatesh Athyam
import './App.css'
const initialUserDetailsList = [
{
uniqueNo: 1,
imageUrl: 'https://assets.ccbp.in/frontend/react-js/esther-howard-img.png',
name: 'Esther Howard',
role: 'Software Developer'
},
{
uniqueNo: 2,
imageUrl: 'https://assets.ccbp.in/frontend/react-js/floyd-miles-img.png',
name: 'Floyd Miles',
role: 'Software Developer'
},
{
uniqueNo: 3,
imageUrl: 'https://assets.ccbp.in/frontend/react-js/jacob-jones-img.png',
name: 'Jacob Jones',
role: 'Software Developer'
},
{
uniqueNo: 4,
imageUrl: 'https://assets.ccbp.in/frontend/react-js/devon-lane-img.png',
name: 'Devon Lane',
role: 'Software Developer'
Venkatesh Athyam
}
]
render() {
const {searchInput, usersDetailsList} = this.state
const searchResults = usersDetailsList.filter(eachUser =>
eachUser.name.includes(searchInput)
)
return (
<div className="app-container">
<h1 className="title">Users List</h1>
<input
type="search"
onChange={this.onChangeSearchInput}
value={searchInput}
/>
<ul className="list-container">
{searchResults.map(eachUser => (
<UserProfile
userDetails={eachUser}
key={eachUser.uniqueNo}
deleteUser={this.deleteUser}
/>
))}
Venkatesh Athyam
</ul>
</div>
)
}
}
Concepts in Focus
• Missing Export Statement
• Missing Import Statement
Venkatesh Athyam
import './index.css'
<p className="counter">Counter</p>
)
}
}
import './index.css'
File: src/components/Counter/index.js
import './index.css'
class Counter {
render() {
return (
<p className="counter">Counter</p>
)
}
}
export default Counter
4. class vs className
Mistake:
File: src/components/Counter/index.js
import './index.css'
5. onclick vs onClick
Mistake:
File: src/components/Counter/index.js
import './index.css'
import './index.css'
)
}
}
export default Counter
Solution:
onIncrement = () => {
const {count} = this.state;
console.log(count);
};
In Arrow functions, this refers to the context in which the code is defined.
Mistake:
File: src/components/Counter/index.js
import './index.css'
Solution:
<button onClick={this.onIncrement}>Increase</button>
Mistake:
onIncrement = () => {
this.state.count = this.state.count + 1;
Venkatesh Athyam
};
Solution:
onIncrement = () => {
this.setState(prevState => ({
count: prevState.count + 1
}));
};
Updating Object:
Mistake:
state = {
person: {name: "Rahul", age: 30}
}
onUpdateAge = () => {
const {person} = this.state
person.age = 29
}
Solution:
state = {
person: {name: "Rahul", age: 30}
}
onUpdateAge = () => {
const {person} = this.state
const newPerson = {...person, age: 29}
this.setState({person: newPerson})
}
Updating List:
Mistake:
onUpdateNumbers = () => {
const {numbers} = this.state
numbers.push(4)
}
Solution:
Venkatesh Athyam
onUpdateNumbers = () => {
const {numbers} = this.state
const updatedNumbers = [...numbers, 4]
this.setState({numbers: updatedNumbers})
}
render() {
this.setState({ count: 0 })
return ({...})
}
Specifying a new state with setState() function causes a new render. If we call
setState from the render() function, this will cause an infinite loop.
When we call setState from the render() function, it will cause an infinite loop.
Mistake:
import { Component } from 'react'
import './index.css'
<button onClick={this.onIncrement()}>Increase</button>
)
}
}
export default Counter
Solution:
import './index.css'
Mistake:
import { Component } from 'react'
import './index.css'
}
render() {
return (
<p className="counter">Counter</p>
<button onClick={this.onIncrement}>Increase</button>
)
}
}
export default Counter
Mistake:
12.1 Fragments
The fragment is an alternate way to return a single JSX element. It groups a list of children without
adding extra nodes to the DOM.
Short Syntax:
Mistake:
File: src/App.js
File: src/components/Welcome/index.js
Debugging
Debugging is the process of finding & fixing the bugs in the code.
We can debug using:
• Browser Developer Tools
• React Developer Tools
On Demand Session:
Concepts in Focus
• Projects Example
1. Projects Example
File: src/App.js
import './App.css'
const tabsList = [
{tabId: 'STATIC', displayText: 'Static'},
{tabId: 'RESPONSIVE', displayText: 'Responsive'},
{tabId: 'DYNAMIC', displayText: 'Dynamic'},
]
const projectsList = [
{
projectId: 0,
category: 'STATIC',
imageURL: 'https://assets.ccbp.in/frontend/react-js/projects-s3-img.png',
title: 'Music Page',
description:
'The music page enables the users to browse through the images of all-time
favorite music albums.',
},
{
Venkatesh Athyam
projectId: 1,
category: 'STATIC',
imageURL: 'https://assets.ccbp.in/frontend/react-js/projects-s4-img.png',
title: 'Tourism Website',
description:
'A tourism website enables the user to browse through the images of popular
destinations.',
},
{
projectId: 2,
category: 'STATIC',
imageURL: 'https://assets.ccbp.in/frontend/react-js/projects-s1-img.png',
title: 'Advanced Technologies',
description:
'A website that gives you a basic understanding of Advanced Technologies.',
},
{
projectId: 3,
category: 'STATIC',
imageURL: 'https://assets.ccbp.in/frontend/react-js/projects-s2-img.png',
title: 'Happy Meals',
description: 'Discover the best foods in over 1,000 restaurants.',
},
{
projectId: 4,
category: 'RESPONSIVE',
imageURL: 'https://assets.ccbp.in/frontend/react-js/projects-r4-img.png',
title: 'VR Website',
description:
'VR Website enables users to explore AR and VR Products and Industry
happenings.',
},
{
projectId: 5,
category: 'RESPONSIVE',
imageURL: 'https://assets.ccbp.in/frontend/react-js/projects-r2-img.png',
title: 'Food Munch',
description: 'Food Much Website is a user-centric food tech website.',
},
Venkatesh Athyam
{
projectId: 6,
category: 'RESPONSIVE',
imageURL: 'https://assets.ccbp.in/frontend/react-js/projects-r3-img.png',
title: 'Portfolio',
description:
'A portfolio is the best alternative for a resume to showcase your skills to the
digital world.',
},
{
projectId: 7,
category: 'RESPONSIVE',
imageURL: 'https://assets.ccbp.in/frontend/react-js/projects-r1-img.png',
title: 'Design',
description:
'A website to showcase the best features and give more information about the
Design tool.',
},
{
projectId: 8,
category: 'DYNAMIC',
imageURL: 'https://assets.ccbp.in/frontend/react-js/projects-d3-img.png',
title: 'Speed Typing Test',
description:
'Speed Typing Test Application is capable of calculating the time to type the
randomly generated quote.',
},
{
projectId: 9,
category: 'DYNAMIC',
imageURL: 'https://assets.ccbp.in/frontend/react-js/projects-d1-img.png',
title: 'Random Joke Page',
description:
'Random Joke Page is an API-based dynamic Web Application that generates a
new joke.',
},
{
projectId: 10,
category: 'DYNAMIC',
Venkatesh Athyam
imageURL: 'https://assets.ccbp.in/frontend/react-js/projects-d2-img.png',
title: 'Sizing An Image',
description:
'This is a dynamic web application capable of adjusting the size of an element
using DOM manipulations.',
},
]
getFilteredProjects = () => {
const {activeTabId} = this.state
const filteredProjects = projectsList.filter(
eachprojectDetails => eachprojectDetails.category === activeTabId,
)
return filteredProjects
}
render() {
const {activeTabId} = this.state
const filteredProjects = this.getFilteredProjects()
return (
<div className="app-container">
<Header />
<h1 className="title">Projects</h1>
<p className="description">
Your skills and achievements showcase your strengths and abilities.
Speak about any new skills or software you learnt to perform the
project responsibilities.
</p>
<ul className="tabs-container">
Venkatesh Athyam
{tabsList.map(tabDetails => (
<TabItem
key={tabDetails.tabId}
tabDetails={tabDetails}
clickTabItem={this.clickTabItem}
isActive={activeTabId === tabDetails.tabId}
/>
))}
</ul>
<ul className="project-list-container">
{filteredProjects.map(projectDetails => (
<ProjectItem
key={projectDetails.projectId}
projectDetails={projectDetails}
/>
))}
</ul>
</div>
)
}
}
export default App
File: src/components/TabItem/index.js
import './index.css'
return (
<li className="tab-item-container ">
<button
Venkatesh Athyam
type="button"
className={`tab-btn ${activeTabBtnClassName}`}
onClick={onClickTabItem}
>
{displayText}
</button>
</li>
)
}
export default TabItem
Note: In the above code, multiple class names can be added using template literals.
File: src/components/Header/index.js
import './index.css'
src="https://res.cloudinary.com/dmwrugc6z/image/upload/v1621681890/
Background_4x_1_bzyjew.png"
alt="Twitter"
/>
</li>
</ul>
</div>
</nav>
)
export default Header
File: src/components/ProjectItem/index.js
import './index.css'
• Installing UUID
• Importing of UUID
• Best Practice
• Updating a Property of an Item inside List
• Contacts App Final Code
1. Third-Party Packages
2. Best Practice
• The state should be immutable. We shouldn’t update the array/object directly.
• The best practice is to create a new array/object from the array/object in the previous state
using the spread operator.
this.state.contactsList = initialContactsList
this.state.contactsList.push(...)
this.setState(prevState => ({
contactsList: [...prevState.contactsList, newContact ],
}))
{...object, newItem}
Exmaple:
File: src/App.js
import './App.css'
const initialContactsList = [
{
id: uuidv4(),
name: 'Ram',
mobileNo: 9999988888,
isFavorite: false,
},
{
id: uuidv4(),
name: 'Pavan',
mobileNo: 8888866666,
isFavorite: true,
},
{
id: uuidv4(),
name: 'Nikhil',
mobileNo: 9999955555,
isFavorite: false,
},
]
state = {
contactsList: initialContactsList,
name: '',
mobileNo: '',
}
toggleIsFavorite = id => {
this.setState(prevState => ({
contactsList: prevState.contactsList.map(eachContact => {
if (id === eachContact.id) {
// eachContact.isFavorite = !eachContact.isFavorite
return {...eachContact, isFavorite: !eachContact.isFavorite}
}
return eachContact
}),
}))
}
this.setState(prevState => ({
contactsList: [...prevState.contactsList, newContact],
name: '',
mobileNo: '',
}))
}
render() {
const {name, mobileNo, contactsList} = this.state
return (
<div className="app-container">
<div className="responsive-container">
<h1 className="heading">Contacts</h1>
<form className="contact-form-container" onSubmit={this.onAddContact}>
<input
value={name}
onChange={this.onChangeName}
className="input"
placeholder="Name"
/>
Venkatesh Athyam
<input
className="input"
value={mobileNo}
onChange={this.onChangeMobileNo}
placeholder="Mobile Number"
/>
<button type="submit" className="button">
Add Contact
</button>
</form>
<ul className="contacts-table">
<li className="table-header">
<p className="table-header-cell name-column">Name</p>
<hr className="separator" />
<p className="table-header-cell">Mobile Number</p>
</li>
{contactsList.map(eachContact => (
<ContactItem
key={eachContact.id}
contactDetails={eachContact}
toggleIsFavorite={this.toggleIsFavorite}
/>
))}
</ul>
</div>
</div>
)
}
Venkatesh Athyam
}
export default App
import './App.css'
const initialContactsList = [
{
id: uuidv4(),
name: 'Ram',
mobileNo: 9999988888,
isFavorite: false,
},
{
id: uuidv4(),
name: 'Pavan',
mobileNo: 8888866666,
isFavorite: true,
},
{
id: uuidv4(),
name: 'Nikhil',
mobileNo: 9999955555,
isFavorite: false,
},
]
mobileNo: '',
}
toggleIsFavorite = id => {
this.setState(prevState => ({
contactsList: prevState.contactsList.map(eachContact => {
if (id === eachContact.id) {
return {...eachContact, isFavorite: !eachContact.isFavorite}
}
return eachContact
}),
}))
}
this.setState(prevState => ({
contactsList: [...prevState.contactsList, newContact],
name: '',
mobileNo: '',
}))
}
render() {
const {name, mobileNo, contactsList} = this.state
return (
<div className="app-container">
<div className="responsive-container">
<h1 className="heading">Contacts</h1>
<form className="contact-form-container" onSubmit={this.onAddContact}>
<input
value={name}
onChange={this.onChangeName}
className="input"
placeholder="Name"
/>
<input
className="input"
value={mobileNo}
onChange={this.onChangeMobileNo}
placeholder="Mobile Number"
/>
<button type="submit" className="button">
Add Contact
</button>
</form>
<ul className="contacts-table">
<li className="table-header">
<p className="table-header-cell name-column">Name</p>
<hr className="separator" />
<p className="table-header-cell">Mobile Number</p>
</li>
{contactsList.map(eachContact => (
<ContactItem
key={eachContact.id}
contactDetails={eachContact}
toggleIsFavorite={this.toggleIsFavorite}
/>
))}
</ul>
</div>
</div>
Venkatesh Athyam
)
}
}
export default App
File: src/components/ContactItem/index.js
import './index.css'
return (
<li className="table-row">
<div className="table-cell name-column">
<p>{name}</p>
</div>
<hr className="separator" />
<div className="table-cell mobile-no-column">
<p className="mobile-no-value">{mobileNo}</p>
<button
type="button"
Venkatesh Athyam
className="favorite-icon-container"
onClick={onClickFavoriteIcon}
>
<img src={starImgUrl} className="favorite-icon" alt="star" />
</button>
</div>
</li>
)
}
export default ContactItem
Concepts in Focus
• Component Life Cycle Phases
• Mounting Phase
• Updating Phase
• Unmounting Phase
• Clock Example
2. Mounting Phase
In this phase, the instance of a component is created and inserted into the DOM.
2.1 Methods
We mainly use the three methods. The three methods are called in the given order:
• constructor()
• render()
Venkatesh Athyam
• componentDidMount()
2.1.1 constructor()
The
constructor()
method is used to set up the initial
state
and class variables.
Syntax:
constructor(props) {
super(props)
//state and class variables
}
We must call the super(props) method before any other statement. Calling super(props) makes
sure that constructor() of the React.Component gets called and initializes the instance.
Initialising State through props
constructor(props) {
super(props)
this.state = { date: props.date }
}
2.1.2 render()
The render() method is used to return the JSX that is displayed in the UI.
2.1.3 componentDidMount()
The componentDidMount() method is used to run statements that require that the component is
already placed in the DOM.
Example: set timers, initiate API calls, etc.
3. Updating Phase
In this phase, the component is updated whenever there is a change in the component's state.
3.1 Methods
3.1.1 render()
The render() method is called whenever there is a change in the component's state.
4. Unmounting Phase
In this phase, the component instance is removed from the DOM.
Venkatesh Athyam
4.1 Methods
4.1.1 componentWillUnmount()
The componentWillUnmount() method is used to cleanup activities performed.
Example: clearing timers, cancelling API calls, etc.
5. Clock Example
File: src/App.js
import {Component} from 'react'
import Clock from './components/Clock'
import './App.css'
Note:
The logical && operator can be handy for conditionally including an element or component.
File: src/components/Clock/index.js
import './index.css'
Concepts in Focus
• Web Apps
• React Router
• Routing Example
1. Web Apps
Web Apps are of two types, based on how we get content:
• Multi-page application (MPA)
• Single-page application (SPA)
2. React Router
In React, we build Single-page applications using React Router.
To implement routing, React Router provides various components:
• BrowserRouter
• Link
• Route
• Switch
2.1 BrowserRouter
To add routing wrap all the Components with
BrowserRouter
.
Venkatesh Athyam
Syntax:
<BrowserRouter>
<Component 1>
<Component 2>
...
</BrowserRouter>
2.2 Link
Link Component creates hyperlinks that allows to navigate around in application.
Syntax:
<Link to="Path"> Display Text</Link>
The to prop specifies absolute path.
2.3 Route
The Route component renders specific UI component when path matches current URL.
2.3.1 Exact
2.3 Switch
The Switch component will only render the first route that matches the path. If no path matches, it
renders the Not Found component.
<Switch>
<Route path="Path1" component={Component1} />
<Route path="Path2" component={Component2} />
<Route component={NotFound} />
</Switch>
3. Routing Example
File: src/App.js
import { BrowserRouter, Route, Switch } from "react-router-dom"
import NotFound from "./components/NotFound";
...
Venkatesh Athyam
File: src/components/Header/index.js
Concepts in Focus
• API Calls
• Fetch
• Route Props
• Match
• BlogsList Example
1 . API Calls
In General we make API Calls inside componentDidMount(). So that it doesn’t block render().
1.1 Fetch
Venkatesh Athyam
Fetch is a promise-based API which returns a response object. In the backend, we use snake_case
for naming conventions.
2. Route Props
When a component is rendered by the Route, some additional props are passed
• match
• location
• history
2.1 Match
The match object contains the information about the path from which the component is rendered.
3. BlogsList Example
File: src/App.js
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import './App.css'
</BrowserRouter>
)
export default App
File: src/components/Header/index.js
import { Link } from 'react-router-dom'
import './index.css'
import 'react-loader-spinner/dist/loader/css/react-spinner-loader.css'
Venkatesh Athyam
import './index.css'
componentDidMount() {
this.getBlogsData()
}
render() {
const { blogsData, isLoading } = this.state
console.log(isLoading)
Venkatesh Athyam
return (
<div className="blog-list-container">
{isLoading ? (
<Loader type="TailSpin" color="#00BFFF" height={50} width={50} />
):(
blogsData.map(item => <BlogItem blogData={item} key={item.id} />)
)}
</div>
)
}
}
export default BlogsList
File: src/components/BlogItem/index.js
import { Link } from 'react-router-dom'
import './index.css'
return (
<Link to={`/blogs/${id}`} className="item-link">
<div className="item-container">
<img className="item-image" src={imageUrl} alt={`item${id}`} />
<div className="item-info">
<p className="item-topic">{topic}</p>
<p className="item-title">{title}</p>
<div className="author-info">
<img className="avatar" src={avatarUrl} alt={`avatar${id}`} />
<p className="author-name">{author}</p>
Venkatesh Athyam
</div>
</div>
</div>
</Link>
)
}
export default BlogItem
File: src/components/About/index.js
import './index.css'
<h1 className="contact-heading">Contact</h1>
</div>
)
export default Contact
File: src/components/BlogItemDetails/index.js
import { Component } from 'react'
import Loader from 'react-loader-spinner'
import 'react-loader-spinner/dist/loader/css/react-spinner-loader.css'
import './index.css'
componentDidMount() {
this.getBlogItemData()
}
const updatedData = {
title: data.title,
imageUrl: data.image_url,
content: data.content,
avatarUrl: data.avatar_url,
author: data.author,
Venkatesh Athyam
}
this.setState({ blogData: updatedData, isLoading: false })
}
renderBlogItemDetails = () => {
const { blogData } = this.state
const { title, imageUrl, content, avatarUrl, author } = blogData
return (
<div className="blog-info">
<h2 className="blog-details-title">{title}</h2>
<div className="author-details">
<img className="author-pic" src={avatarUrl} alt={author} />
<p className="details-author-name">{author}</p>
</div>
<img className="blog-image" src={imageUrl} alt={title} />
<p className="blog-content">{content}</p>
</div>
)
}
render() {
const { isLoading } = this.state
return (
<div className="blog-container">
{isLoading ? (
<Loader type="TailSpin" color="#00BFFF" height={50} width={50} />
):(
this.renderBlogItemDetails()
)}
</div>
Venkatesh Athyam
)
}
}
export default BlogItemDetails
File: src/components/NotFound/index.js
import './index.css'
Concepts in Focus
• Rendering Promise Object
• Using Link and Route Components without BrowserRouter
• Providing Wrong Route Path
• Missing exact keyword
• Missing Switch
• Placing Common component inside Switch
• Providing the same PATH for multiple Routes
• Missing Colon(:) while providing Path Parameters
• Accessing Promise Object
• Ordering of Routes inside Switch
.
File: src/components/BlogsList/index.js
import 'react-loader-spinner/dist/loader/css/react-spinner-loader.css'
import './index.css'
render() {
const { blogsData, isLoading } = this.state
console.log(isLoading)
return (
<div className="blog-list-container">
{this.getBlogsData()}
</div>
)
}
}
export default BlogsList
Solution:
File: src/components/BlogsList/index.js
import { Component } from 'react'
import Loader from 'react-loader-spinner'
import 'react-loader-spinner/dist/loader/css/react-spinner-loader.css'
import BlogItem from '../BlogItem'
import './index.css'
class BlogsList extends Component {
state = { isLoading: true, blogsData: [] }
componentDidMount() {
this.getBlogsData()
}
import './App.css'
Solution:
File: src/App.js
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import './App.css'
import './index.css'
import './App.css'
import './App.css'
import './index.css'
import './App.css'
import './App.css'
5. Missing Switch
Mistake:
File: src/App.js
import { BrowserRouter, Route} from 'react-router-dom'
import './App.css'
<BrowserRouter>
<Header />
<Route exact path="/" component={BlogsList} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
<Route path="/blogs/:id" component={BlogItemDetails} />
<Route component={NotFound} />
</BrowserRouter>
)
export default App
Solution:
File: src/App.js
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import './App.css'
</Switch>
</BrowserRouter>
)
export default App
import './App.css'
import './App.css'
import './App.css'
import './App.css'
import './App.css'
import './App.css'
import './index.css'
Cookies.set('jwt_token', jwtToken, {
expires: 30,
})
history.replace('/')
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
placeholder="Password"
/>
</>
)
}
renderUsernameField = () => {
const {username} = this.state
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
Venkatesh Athyam
</label>
<input
type="text"
id="username"
className="username-input-filed"
value={username}
onChange={this.onChangeUsername}
placeholder="Username"
/>
</>
)
}
render() {
const {showSubmitError, errorMsg} = this.state
const jwtToken = Cookies.get('jwt_token')
if (jwtToken !== undefined) {
return <Redirect to="/" />
}
return (
<div className="login-form-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
Venkatesh Athyam
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
<button type="submit" className="login-button">
Login
</button>
{showSubmitError && <p className="error-message">{errorMsg}</p>}
</form>
</div>
)
}
}
export default LoginForm
Solution:
File: src/components/LoginForm/index.js
import './index.css'
Cookies.set('jwt_token', jwtToken, {
expires: 30,
})
history.replace('/')
}
body: JSON.stringify(userDetails),
}
const response = await fetch(url, options)
const data = await response.json()
console.log(data.error_msg)
if (response.ok === true) {
this.onSubmitSuccess(data.jwt_token)
} else {
this.onSubmitFailure(data.error_msg)
}
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
placeholder="Password"
/>
</>
)
}
renderUsernameField = () => {
Venkatesh Athyam
render() {
const {showSubmitError, errorMsg} = this.state
const jwtToken = Cookies.get('jwt_token')
if (jwtToken !== undefined) {
return <Redirect to="/" />
}
return (
<div className="login-form-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
Venkatesh Athyam
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
<button type="submit" className="login-button">
Login
</button>
{showSubmitError && <p className="error-message">{errorMsg}</p>}
</form>
</div>
)
}
}
export default LoginForm
import './App.css'
import './App.css'
Venkatesh Athyam
Concepts in Focus
• Client-Server Communication
• Authentication
• Authorization
• Authentication Flow
• Route Parameters
• History
• E-Commerce Application
1. Client-Server Communication
Venkatesh Athyam
1.1 Authentication
Authentication is the process of verifying a user's identity.
1.2 Authorization
Authorization is the process of verifying whether the user is authenticated and permitted to perform
some actions like accessing resources, etc.
Example:
After successful authentication, employees are only allowed to access certain resources based on
their roles.
• Admin can Read, Create, Delete, and Update the Resources
• User can only Read and Create the Resources
2. Authentication Flow
3. Route Parameters
When a component is rendered by the Route, some additional props are passed.
They are:
Venkatesh Athyam
• match
• history
• location
3.1 History
The history object has some methods to control the navigation in the browser, and it also maintains
the history of the routes we navigated.
It has the following methods to control the navigation in the browser:
• push()
• replace()
• go()
• goBack()
• goForward()
, etc.
The history.push() and history.replace() methods are used to navigate to other routes
programmatically.
3.1.1 history.push()
With the history.push() method, the user can go forward and backwards in the browser, and the
URL will change.
Syntax:
history.push("PATH");
3.1.2 history.replace()
The history.replace() method replaces the current URL with new one. The user can't go backwards
to the previous URL.
Syntax:
history.replace("PATH");
4. E-Commerce Application
• Make an Authentication Request to Login API
• Handle Login API Response
• On Login Success
• On Login Failure
• Store the JWT Token
Authenticated Credentials:
Username: henry
password: henry_the_developer
Username: david
password: the_miller@23
Venkatesh Athyam
Username: robert
password: WilsonRobert45
Username: mosh
password: DevMosh22
Username: rahul
password: rahul@2021
Username: praneetha
password: praneetha@2021
File: src/App.js
import {BrowserRouter, Route, Switch} from 'react-router-dom'
import './App.css'
import './index.css'
onSubmitSuccess = () => {
const {history} = this.props
history.replace('/')
}
this.setState({username: event.target.value})
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
/>
</>
)
}
renderUsernameField = () => {
const {username} = this.state
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
</label>
Venkatesh Athyam
<input
type="text"
id="username"
className="username-input-filed"
value={username}
onChange={this.onChangeUsername}
/>
</>
)
}
render() {
return (
<div className="login-form-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
Venkatesh Athyam
we are in a revolution. Your fashion makes you been seen and heard
that way you are. So, celebrate the seasons new and exciting fashion
in your own way.
</p>
<button type="button" className="shop-now-button">
Shop Now
</button>
</div>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-img.png"
alt="dresses to be noticed"
className="home-desktop-img"
/>
</div>
</>
)
export default Home
File: src/components/Cart/index.js
import Header from '../Header'
import './index.css'
)
export default Cart
File: src/components/Header/index.js
import {Link} from 'react-router-dom'
import './index.css'
className="logout-icon"
/>
</button>
</div>
</nav>
)
export default Header
File: src/components/Products/index.js
import Header from '../Header'
import './index.css'
alt="not-found"
className="not-found-img"
/>
</div>
);
export default NotFound;
Concepts in Focus
• JWT Token
• Storage Mechanisms
• Cookies
• Why Cookies?
• Cookies vs Local Storage
• Third Party Package
js-cookie
• Redirect Component
• withRouter
• E-Commerce Application
1. JWT Token
JSON Web Token is a standard used to create Access Tokens. These access tokens are also called
JWT Tokens.
The client uses these access tokens on every subsequent request to communicate with the Server.
Note: While making HTTP Request, we have to send an access token in the HTTP Headers with
the key Authorization.
Example:
Authorization: Bearer jwt_token
2. Storage Mechanisms
• Client-Side Data Storage
• Storing Data on the Client
• Server-Side Data Storage
• Storing Data on the Server using some kind of Database
Venkatesh Athyam
3. Cookies
A cookie is a piece of data that is stored on the user's computer by the web browser.
A cookie is made up of:
• Name & Value
• Expires − The date the cookie will expire. If this is blank, the cookie will expire when the
visitor quits the browser.
• Domain − The domain name of your site.
• Path − The path to the directory or web page that set the cookie. This may be blank if you
want to retrieve the cookie from any directory or page.
• Secure − If this field contains the word "secure", then the cookie may only be retrieved with
a secure server. If this field is blank, no such restriction exists, etc.
3.3.1 Cookies.set()
Syntax:
Cookies.set('CookieName', 'CookieValue', {expires: DAYS});
Example:
Cookies.set('ACCESS_TOKEN', 'Us1L90PXl...', {expires: 1});
3.3.2 Cookies.get()
It returns undefined if the cookie expires or does not exist.
Syntax:
Cookies.get('CookieName');
Example:
Cookies.get('ACCESS_TOKEN');
3.3.3 Cookies.remove()
Syntax:
Cookies.remove('CookieName');
Example:
Cookies.remove('ACCESS_TOKEN');
4. Redirect Component
The react-router-dom provides the Redirect component. It can be used whenever we want to
redirect to another path.
Syntax:
<Redirect to="PATH" />
Example:
<Redirect to="/login" />
5. withRouter
The history prop will be available for only components which are directly given for Route.
Venkatesh Athyam
To provide history prop to other components, we can wrap it with the withRouter function while
exporting it.
Example:
import { withRouter} from 'react-router-dom'
...
export default withRouter(ComponentName)
6. E-Commerce Application
• Make an Authentication Request to Login API
• Handle Login API Response
• On Login Success
• On Login Failure
• Store the JWT Token
File: src/App.js
import {BrowserRouter, Route, Switch} from 'react-router-dom'
import './App.css'
File: src/components/Cart/index.js
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-cart-img.png"
alt="cart"
className="cart-img"
/>
</div>
</>
)
File: src/components/Header/index.js
import './index.css'
className="logout-mobile-btn"
onClick={onClickLogout}
>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-log-out-img.png"
alt="logout icon"
className="logout-icon"
/>
</button>
</div>
</nav>
)
}
export default withRouter(Header)
File: src/components/Home/index.js
import './index.css'
return (
<>
<Header />
<div className="home-container">
<div className="home-content">
<h1 className="home-heading">Clothes That Get YOU Noticed</h1>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-img.png"
alt="dresses to be noticed"
className="home-mobile-img"
/>
<p className="home-description">
Fashion is part of the daily air and it does not quite help that it
changes all the time. Clothes have always been a marker of the era
and we are in a revolution. Your fashion makes you been seen and
heard that way you are. So, celebrate the seasons new and exciting
fashion in your own way.
</p>
<button type="button" className="shop-now-button">
Shop Now
</button>
</div>
<img
Venkatesh Athyam
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-img.png"
alt="dresses to be noticed"
className="home-desktop-img"
/>
</div>
</>
)
}
File: src/components/LoginForm/index.js
}
const response = await fetch(url, options)
const data = await response.json()
if (response.ok === true) {
this.onSubmitSuccess(data.jwt_token)
} else {
this.onSubmitFailure(data.error_msg)
}
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
/>
</>
)
}
renderUsernameField = () => {
const {username} = this.state
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
</label>
<input
type="text"
id="username"
className="username-input-filed"
value={username}
onChange={this.onChangeUsername}
/>
</>
)
}
render() {
const {showSubmitError, errorMsg} = this.state
return (
<div className="login-form-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
Venkatesh Athyam
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
<button type="submit" className="login-button">
Login
</button>
{showSubmitError && <p className="error-message">*{errorMsg}</p>}
</form>
</div>
)
}
}
File: src/components/NotFound/index.js
import './index.css'
File: src/components/Products/index.js
import './index.css'
<Header />
<div className="products-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-products-img.png"
alt="products"
className="products-img"
/>
</div>
</>
)
Concepts in Focus
• Router Switch
• Wrapper Component
• Protected Route
• E-Commerce Application
1.Router Switch
Switch can have any React Component inside it
• Route
• User defined Component
• Redirect
2. Wrapper Component
Redirection Logic can be reused by separating out into a React Component called Wrapper
Component. Each route will be wrapped with it.
3. E-Commerce Application
File: src/App.js
import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom";
import "./App.css";
File: src/components/AllProductsSection/index.js
componentDidMount() {
Venkatesh Athyam
this.getProducts();
}
renderProductsList = () => {
const { productsList } = this.state;
return (
<div>
<h1 className="products-list-heading">All Products</h1>
<ul className="products-list">
{productsList.map((product) => (
<ProductCard productData={product} key={product.id} />
))}
</ul>
</div>
);
};
render() {
return <>{this.renderProductsList()}</>;
}
}
File: src/components/Cart/index.js
Venkatesh Athyam
File: src/components/Header/index.js
import "./index.css";
type="button"
className="logout-desktop-btn"
onClick={onClickLogout}
>
Logout
</button>
<button
type="button"
className="logout-mobile-btn"
onClick={onClickLogout}
>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-log-out-img.png"
alt="logout icon"
className="logout-icon"
/>
</button>
</div>
</nav>
);
};
export default withRouter(Header);
File: src/components/Home/index.js
alt="dresses to be noticed"
className="home-desktop-img"
/>
</div>
</>
);
File: src/components/LoginForm/index.js
import "./index.css";
Cookies.set("jwt_token", jwtTkoken, {
expires: 30,
path: "/",
});
history.replace("/");
};
renderPasswordField = () => {
const { password } = this.state;
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
/>
</>
);
};
renderUsernameField = () => {
const { username } = this.state;
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
</label>
<input
type="text"
id="username"
className="username-input-filed"
value={username}
onChange={this.onChangeUsername}
/>
</>
);
};
render() {
Venkatesh Athyam
File: src/components/NotFound/index.js
import "./index.css";
File: src/components/ProductCard/index.js
import "./index.css";
return (
<li className="product-item">
<img src={imageUrl} alt="product" className="thumbnail" />
<h1 className="title">{title}</h1>
<p className="brand">by {brand}</p>
<div className="product-details">
<p className="price">Rs {price}/-</p>
<div className="rating-container">
<p className="rating">{rating}</p>
<img
src="https://assets.ccbp.in/frontend/react-js/star-img.png"
alt="star"
className="star"
/>
</div>
</div>
</li>
);
};
export default ProductCard;
File: src/components/Products/index.js
import AllProductsSection from "../AllProductsSection";
import "./index.css";
File: src/components/ProtectedRoute/index.js
import './index.css'
onChangeUsername(event){
this.setState({username: event.target.value})
}
Cookies.set('jwt_token', jwtToken, {
expires: 30,
})
history.replace('/')
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
placeholder="Password"
/>
</>
)
}
renderUsernameField = () => {
Venkatesh Athyam
render() {
const {showSubmitError, errorMsg} = this.state
const jwtToken = Cookies.get('jwt_token')
if (jwtToken !== undefined) {
return <Redirect to="/" />
}
return (
<div className="login-form-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
<button type="submit" className="login-button">
Login
</button>
{showSubmitError && <p className="error-message">{errorMsg}</p>}
</form>
</div>
)
}
Venkatesh Athyam
Explanation:
• In Class Component, the function definition will execute in the browser context, so the value
of this will be null.
• Component Life Cycle
Methods(componentDidMount,render,constructor,componentWillUnmount) are extended
from React Component. As they run in React Context, there is no need to write them in
arrow functions.
Solution:
File: src/components/LoginForm/index.js
import {Component} from 'react'
import Cookies from 'js-cookie'
import {Redirect} from 'react-router-dom'
import './index.css'
Cookies.set('jwt_token', jwtToken, {
expires: 30,
})
history.replace('/')
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
placeholder="Password"
/>
</>
)
}
renderUsernameField = () => {
const {username} = this.state
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
</label>
<input
type="text"
id="username"
className="username-input-filed"
Venkatesh Athyam
value={username}
onChange={this.onChangeUsername}
placeholder="Username"
/>
</>
)
}
render() {
const {showSubmitError, errorMsg} = this.state
const jwtToken = Cookies.get('jwt_token')
if (jwtToken !== undefined) {
return <Redirect to="/" />
}
return (
<div className="login-form-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
Venkatesh Athyam
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
<button type="submit" className="login-button">
Login
</button>
{showSubmitError && <p className="error-message">{errorMsg}</p>}
</form>
</div>
)
}
}
export default LoginForm
import './index.css'
return (
<nav className="nav-header">
<div className="nav-content">
<div className="nav-bar-mobile-logo-container">
Venkatesh Athyam
<img
className="website-logo"
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
alt="website logo"
/>
<div className="nav-bar-large-container">
<img
className="website-logo"
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
alt="website logo"
/>
<ul className="nav-menu">
<li className="nav-menu-item">
<Link to="/" className="nav-link">
Home
</Link>
</li>
<li className="nav-menu-item">
<Link to="/products" className="nav-link">
Products
Venkatesh Athyam
</Link>
</li>
<li className="nav-menu-item">
<Link to="/cart" className="nav-link">
Cart
</Link>
</li>
</ul>
<button
type="button"
className="logout-desktop-btn"
onClick={onClickLogout}
>
Logout
</button>
</div>
</div>
<div className="nav-menu-mobile">
<ul className="nav-menu-list-mobile">
<li className="nav-menu-item-mobile">
<Link to="/" className="nav-link">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-icon.png"
alt="nav home"
className="nav-bar-image"
/>
</Link>
</li>
<li className="nav-menu-item-mobile">
<Link to="/products" className="nav-link">
Venkatesh Athyam
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-products-icon.png"
alt="nav products"
className="nav-bar-image"
/>
</Link>
</li>
<li className="nav-menu-item-mobile">
<Link to="/cart" className="nav-link">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-cart-icon.png"
alt="nav cart"
className="nav-bar-image"
/>
</Link>
</li>
</ul>
</div>
</nav>
)
}
export default withRouter(Header)
Explanation:
• Redirect Component returns JSX and it is used to render the UI in the specific Route.
• To navigate to the specific Routes in event handlers or callbacks used the history object.
Solution:
File: src/components/Header/index.js
import {Link, withRouter} from 'react-router-dom'
import './index.css'
Venkatesh Athyam
return (
<nav className="nav-header">
<div className="nav-content">
<div className="nav-bar-mobile-logo-container">
<img
className="website-logo"
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
alt="website logo"
/>
<div className="nav-bar-large-container">
<img
className="website-logo"
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
Venkatesh Athyam
alt="website logo"
/>
<ul className="nav-menu">
<li className="nav-menu-item">
<Link to="/" className="nav-link">
Home
</Link>
</li>
<li className="nav-menu-item">
<Link to="/products" className="nav-link">
Products
</Link>
</li>
<li className="nav-menu-item">
<Link to="/cart" className="nav-link">
Cart
</Link>
</li>
</ul>
<button
type="button"
className="logout-desktop-btn"
onClick={onClickLogout}
>
Logout
</button>
</div>
</div>
<div className="nav-menu-mobile">
<ul className="nav-menu-list-mobile">
Venkatesh Athyam
<li className="nav-menu-item-mobile">
<Link to="/" className="nav-link">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-icon.png"
alt="nav home"
className="nav-bar-image"
/>
</Link>
</li>
<li className="nav-menu-item-mobile">
<Link to="/products" className="nav-link">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-products-icon.png"
alt="nav products"
className="nav-bar-image"
/>
</Link>
</li>
<li className="nav-menu-item-mobile">
<Link to="/cart" className="nav-link">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-cart-icon.png"
alt="nav cart"
className="nav-bar-image"
/>
</Link>
</li>
</ul>
</div>
</nav>
)
Venkatesh Athyam
}
export default withRouter(Header)
import './index.css'
Cookies.set('jwt_token', jwtToken, {
expires: 30,
})
history.replace('/')
}
renderPasswordField = () => {
Venkatesh Athyam
renderUsernameField = () => {
const {username} = this.state
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
</label>
<input
type="text"
id="username"
className="username-input-filed"
value={username}
onChange={this.onChangeUsername}
placeholder="Username"
Venkatesh Athyam
/>
</>
)
}
render() {
const {showSubmitError, errorMsg} = this.state
const jwtToken = Cookies.get('jwt_token')
const {history} = this.props
if (jwtToken !== undefined) {
history.replace('/')
}
return (
<div className="login-form-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
Venkatesh Athyam
import './index.css'
Cookies.set('jwt_token', jwtToken, {
expires: 30,
})
history.replace('/')
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
placeholder="Password"
/>
</>
)
}
renderUsernameField = () => {
const {username} = this.state
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
Venkatesh Athyam
</label>
<input
type="text"
id="username"
className="username-input-filed"
value={username}
onChange={this.onChangeUsername}
placeholder="Username"
/>
</>
)
}
render() {
const {showSubmitError, errorMsg} = this.state
const jwtToken = Cookies.get('jwt_token')
if (jwtToken !== undefined) {
return <Redirect to="/" />
}
return (
<div className="login-form-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
Venkatesh Athyam
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
<button type="submit" className="login-button">
Login
</button>
{showSubmitError && <p className="error-message">{errorMsg}</p>}
</form>
</div>
)
}
}
export default LoginForm
import './index.css'
Cookies.remove('jwt_token')
history.replace('/login')
}
return (
<nav className="nav-header">
<div className="nav-content">
<div className="nav-bar-mobile-logo-container">
<img
className="website-logo"
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
alt="website logo"
/>
<div className="nav-bar-large-container">
<img
className="website-logo"
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
alt="website logo"
/>
<ul className="nav-menu">
<li className="nav-menu-item">
Venkatesh Athyam
<li className="nav-menu-item">
<Link to="/products" className="nav-link">
Products
</Link>
</li>
<li className="nav-menu-item">
<Link to="/cart" className="nav-link">
Cart
</Link>
</li>
</ul>
<button
type="button"
className="logout-desktop-btn"
onClick={onClickLogout}
>
Logout
</button>
</div>
</div>
<div className="nav-menu-mobile">
<ul className="nav-menu-list-mobile">
<li className="nav-menu-item-mobile">
<Link to="/" className="nav-link">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-icon.png"
Venkatesh Athyam
alt="nav home"
className="nav-bar-image"
/>
</Link>
</li>
<li className="nav-menu-item-mobile">
<Link to="/products" className="nav-link">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-products-icon.png"
alt="nav products"
className="nav-bar-image"
/>
</Link>
</li>
<li className="nav-menu-item-mobile">
<Link to="/cart" className="nav-link">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-cart-icon.png"
alt="nav cart"
className="nav-bar-image"
/>
</Link>
</li>
</ul>
</div>
</nav>
)
}
export default Header
Solution:
File: src/components/Header/index.js
Venkatesh Athyam
import './index.css'
return (
<nav className="nav-header">
<div className="nav-content">
<div className="nav-bar-mobile-logo-container">
<img
className="website-logo"
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
alt="website logo"
/>
</div>
<div className="nav-bar-large-container">
<img
className="website-logo"
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
alt="website logo"
/>
<ul className="nav-menu">
<li className="nav-menu-item">
<Link to="/" className="nav-link">
Home
</Link>
</li>
<li className="nav-menu-item">
<Link to="/products" className="nav-link">
Products
</Link>
</li>
<li className="nav-menu-item">
<Link to="/cart" className="nav-link">
Cart
</Link>
</li>
</ul>
<button
type="button"
className="logout-desktop-btn"
onClick={onClickLogout}
>
Venkatesh Athyam
Logout
</button>
</div>
</div>
<div className="nav-menu-mobile">
<ul className="nav-menu-list-mobile">
<li className="nav-menu-item-mobile">
<Link to="/" className="nav-link">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-icon.png"
alt="nav home"
className="nav-bar-image"
/>
</Link>
</li>
<li className="nav-menu-item-mobile">
<Link to="/products" className="nav-link">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-products-icon.png"
alt="nav products"
className="nav-bar-image"
/>
</Link>
</li>
<li className="nav-menu-item-mobile">
<Link to="/cart" className="nav-link">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-cart-icon.png"
alt="nav cart"
className="nav-bar-image"
/>
Venkatesh Athyam
</Link>
</li>
</ul>
</div>
</nav>
)
}
export default withRouter(Header)
import './index.css'
Cookies.set('jwt_token', jwtToken, {
expires: 30,
})
history.replace('/')
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
placeholder="Password"
/>
</>
)
}
renderUsernameField = () => {
const {username} = this.state
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
Venkatesh Athyam
</label>
<input
type="text"
id="username"
className="username-input-filed"
value={username}
onChange={this.onChangeUsername}
placeholder="Username"
/>
</>
)
}
render() {
const {showSubmitError, errorMsg} = this.state
const jwtToken = Cookies.get('jwt_token')
if (jwtToken !== undefined) {
return <Redirect to="/" />
}
return (
<div className="login-form-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
Venkatesh Athyam
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
<button type="submit" className="login-button">
Login
</button>
{showSubmitError && <p className="error-message">{errorMsg}</p>}
</form>
</div>
)
}
}
export default LoginForm
Solution:
File: src/components/LoginForm/index.js
import {Component} from 'react'
import Cookies from 'js-cookie'
import {Redirect} from 'react-router-dom'
import './index.css'
Cookies.set('jwt_token', jwtToken, {
expires: 30,
})
history.replace('/')
}
}
const response = await fetch(url, options)
const data = await response.json()
console.log(data.error_msg)
if (response.ok === true) {
this.onSubmitSuccess(data.jwt_token)
} else {
this.onSubmitFailure(data.error_msg)
}
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
placeholder="Password"
/>
</>
)
}
renderUsernameField = () => {
const {username} = this.state
Venkatesh Athyam
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
</label>
<input
type="text"
id="username"
className="username-input-filed"
value={username}
onChange={this.onChangeUsername}
placeholder="Username"
/>
</>
)
}
render() {
const {showSubmitError, errorMsg} = this.state
const jwtToken = Cookies.get('jwt_token')
if (jwtToken !== undefined) {
return <Redirect to="/" />
}
return (
<div className="login-form-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
Venkatesh Athyam
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
<button type="submit" className="login-button">
Login
</button>
{showSubmitError && <p className="error-message">{errorMsg}</p>}
</form>
</div>
)
}
}
export default LoginForm
import './index.css'
state = {
userName: '',
password: '',
showSubmitError: false,
errorMsg: '',
}
Cookies.set('jwt_token', jwtToken, {
expires: 30,
})
history.replace('/')
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
placeholder="Password"
/>
Venkatesh Athyam
</>
)
}
renderUsernameField = () => {
const {username} = this.state
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
</label>
<input
type="text"
id="username"
className="username-input-filed"
value={username}
onChange={this.onChangeUsername}
placeholder="Username"
/>
</>
)
}
render() {
const {showSubmitError, errorMsg} = this.state
const jwtToken = Cookies.get('jwt_token')
if (jwtToken !== undefined) {
return <Redirect to="/" />
}
return (
<div className="login-form-container">
<img
Venkatesh Athyam
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
<button type="submit" className="login-button">
Login
</button>
{showSubmitError && <p className="error-message">{errorMsg}</p>}
</form>
</div>
)
}
}
export default LoginForm
Solution:
File: src/components/LoginForm/index.js
import './index.css'
Cookies.set('jwt_token', jwtToken, {
expires: 30,
})
history.replace('/')
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
</label>
<input
type="password"
id="password"
Venkatesh Athyam
className="password-input-filed"
value={password}
onChange={this.onChangePassword}
placeholder="Password"
/>
</>
)
}
renderUsernameField = () => {
const {username} = this.state
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
</label>
<input
type="text"
id="username"
className="username-input-filed"
value={username}
onChange={this.onChangeUsername}
placeholder="Username"
/>
</>
)
}
render() {
const {showSubmitError, errorMsg} = this.state
const jwtToken = Cookies.get('jwt_token')
if (jwtToken !== undefined) {
Venkatesh Athyam
1. Integrating APIs
3. E-Commerce Application
File: src/App.js
import {BrowserRouter, Route, Switch, Redirect} from 'react-router-dom'
import './App.css'
import './index.css'
componentDidMount() {
this.getProducts()
}
imageUrl: product.image_url,
rating: product.rating,
}))
this.setState({
productsList: updatedData,
isLoading: false,
})
}
}
renderProductsList = () => {
const {productsList} = this.state
return (
<>
<h1 className="products-list-heading">All Products</h1>
<ul className="products-list">
{productsList.map(product => (
<ProductCard productData={product} key={product.id} />
))}
</ul>
</>
)
}
renderLoader = () => (
<div className="products-loader-container">
<Loader type="ThreeDots" color="#0b69ff" height="50" width="50" />
</div>
)
render() {
const {isLoading} = this.state
Venkatesh Athyam
File: src/components/Header/index.js
import './index.css'
alt="website logo"
/>
</Link>
<ul className="nav-menu">
<Link to="/" className="nav-link">
<li>Home</li>
</Link>
<Link to="/products" className="nav-link">
<li>Products</li>
</Link>
<Link to="/cart" className="nav-link">
<li>Cart</li>
</Link>
</ul>
<button
type="button"
className="logout-desktop-btn"
onClick={onClickLogout}
>
Logout
</button>
<button
type="button"
className="logout-mobile-btn"
onClick={onClickLogout}
>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-log-out-img.png"
alt="logout icon"
className="logout-icon"
/>
</button>
</div>
<div className="nav-menu-mobile">
<ul className="nav-menu-list-mobile">
<Link to="/">
<li className="nav-menu-item-mobile">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-icon.png"
alt="nav home"
className="nav-bar-image"
/>
</li>
</Link>
<Link to="/products">
<li className="nav-menu-item-mobile">
Venkatesh Athyam
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-products-icon.png"
alt="nav products"
className="nav-bar-image"
/>
</li>
</Link>
<Link to="/cart">
<li className="nav-menu-item-mobile">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-cart-icon.png"
alt="nav cart"
className="nav-bar-image"
/>
</li>
</Link>
</ul>
</div>
</nav>
)
}
export default withRouter(Header)
File: src/components/Home/index.js
return (
Venkatesh Athyam
<>
<Header />
<div className="home-container">
<div className="home-content">
<h1 className="home-heading">Clothes That Get YOU Noticed</h1>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-img.png"
alt="clothes to be noticed"
className="home-mobile-img"
/>
<p className="home-description">
Fashion is part of the daily air and it does not quite help that it
changes all the time. Clothes have always been a marker of the era
and we are in a revolution. Your fashion makes you been seen and
heard that way you are. So, celebrate the seasons new and exciting
fashion in your own way.
</p>
<Link to="/products">
<button type="button" className="shop-now-button">
Shop Now
</button>
</Link>
</div>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-img.png"
alt="dresses to be noticed"
className="home-desktop-img"
/>
Venkatesh Athyam
</div>
</>
)
}
import './index.css'
Cookies.set('jwt_token', jwtToken, {
expires: 30,
path: '/',
})
history.replace('/')
}
renderPasswordField = () => {
Venkatesh Athyam
renderUsernameField = () => {
const {username} = this.state
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
</label>
<input
type="text"
id="username"
className="username-input-field"
value={username}
onChange={this.onChangeUsername}
/>
</>
Venkatesh Athyam
)
}
render() {
const {showSubmitError, errorMsg} = this.state
const jwtToken = Cookies.get('jwt_token')
if (jwtToken !== undefined) {
return <Redirect to="/" />
}
return (
<div className="login-form-container">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-mobile-image"
alt="website logo"
/>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-login-img.png"
className="login-image"
alt="website login"
/>
<form className="form-container" onSubmit={this.submitForm}>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-logo-img.png"
className="login-website-logo-desktop-image"
alt="website logo"
/>
<div className="input-container">{this.renderUsernameField()}</div>
<div className="input-container">{this.renderPasswordField()}</div>
<button type="submit" className="login-button">
Login
</button>
Venkatesh Athyam
File: src/components/PrimeDealsSection/index.js
import {Component} from 'react'
import Cookies from 'js-cookie'
import Loader from 'react-loader-spinner'
const apiStatusConstants = {
initial: 'INITIAL',
success: 'SUCCESS',
Venkatesh Athyam
failure: 'FAILURE',
inProgress: 'IN_PROGRESS',
}
componentDidMount() {
this.getPrimeDeals()
}
title: product.title,
brand: product.brand,
price: product.price,
id: product.id,
imageUrl: product.image_url,
rating: product.rating,
}))
this.setState({
primeDeals: updatedData,
apiStatus: apiStatusConstants.success,
})
}
if (response.status === 401) {
this.setState({
apiStatus: apiStatusConstants.failure,
})
}
}
renderPrimeDealsList = () => {
const {primeDeals} = this.state
return (
<div>
<h1 className="primedeals-list-heading">Exclusive Prime Deals</h1>
<ul className="products-list">
{primeDeals.map(product => (
<ProductCard productData={product} key={product.id} />
))}
</ul>
</div>
)
}
Venkatesh Athyam
renderPrimeDealsFailureView = () => (
<img
src="https://assets.ccbp.in/frontend/react-js/exclusive-deals-banner-img.png"
alt="Register Prime"
className="register-prime-image"
/>
)
renderLoadingView = () => (
<div className="products-loader-container">
<Loader type="ThreeDots" color="#0b69ff" height="50" width="50" />
</div>
)
render() {
const {apiStatus} = this.state
switch (apiStatus) {
case apiStatusConstants.success:
return this.renderPrimeDealsList()
case apiStatusConstants.failure:
return this.renderPrimeDealsFailureView()
case apiStatusConstants.inProgress:
return this.renderLoadingView()
default:
return null
}
}
}
export default PrimeDealsSection
File: src/components/ProductCard/index.js
import './index.css'
Venkatesh Athyam
return (
<li className="product-item">
<img src={imageUrl} alt="product" className="thumbnail" />
<h1 className="title">{title}</h1>
<p className="brand">by {brand}</p>
<div className="product-details">
<p className="price">Rs {price}/-</p>
<div className="rating-container">
<p className="rating">{rating}</p>
<img
src="https://assets.ccbp.in/frontend/react-js/star-img.png"
alt="star"
className="star"
/>
</div>
</div>
</li>
)
}
export default ProductCard
File: src/components/Products/index.js
import AllProductsSection from '../AllProductsSection'
import PrimeDealsSection from '../PrimeDealsSection'
import './index.css'
Venkatesh Athyam
4. Best Practices
</>
}
renderPrimeDeals = () => {
const { apiStatus } = this.state;
switch (apiStatus) {
Venkatesh Athyam
case apiStatusConstants.success:
return this.renderPrimeDealsSuccessView();
case apiStatusConstants.failure:
return this.renderPrimeDealsFailureView();
case apiStatusConstants.inProgress:
return this.renderLoader();
default:
return null;
}
};
render() {
return <>{this.renderPrimeDeals()}</>
}
}
export default PrimeDealsSection
Sorting Products
Concepts in Focus
• setState() Callback Function
• React Icons
• Installing React Icons
• Searching React Icons
• Importing React Icons
• Sorting Products
2. React Icons
• React-icons is a third-party package contains bundle of icons like bootstrap, font awesome,
material icons etc..,
• Check react-icons website here .
Venkatesh Athyam
<BsFilterRight />
<FaFacebookF />
<MdDelete />
</div>
);
};
export default ReactIcon;
3. Sorting Products
File: src/components/AllProductsSection
import {Component} from 'react'
import Loader from 'react-loader-spinner'
import Cookies from 'js-cookie'
const sortbyOptions = [
{
optionId: 'PRICE_HIGH',
displayText: 'Price (High-Low)',
},
{
optionId: 'PRICE_LOW',
displayText: 'Price (Low-High)',
},
]
isLoading: false,
activeOptionId: sortbyOptions[0].optionId,
}
componentDidMount() {
this.getProducts()
}
this.setState({
productsList: updatedData,
isLoading: false,
})
}
}
renderProductsList = () => {
const {productsList, activeOptionId} = this.state
return (
<>
<ProductsHeader
activeOptionId={activeOptionId}
sortbyOptions={sortbyOptions}
updateActiveOptionId={this.updateActiveOptionId}
/>
<ul className="products-list">
{productsList.map(product => (
<ProductCard productData={product} key={product.id} />
))}
</ul>
</>
)
}
renderLoader = () => (
<div className="products-loader-container">
<Loader type="ThreeDots" color="#0b69ff" height="50" width="50" />
Venkatesh Athyam
</div>
)
render() {
const {isLoading} = this.state
return isLoading ? this.renderLoader() : this.renderProductsList()
}
}
export default AllProductsSection
File: src/components/Cart
import Header from '../Header'
import './index.css'
import './index.css'
Venkatesh Athyam
>
Logout
</button>
<button
type="button"
className="logout-mobile-btn"
onClick={onClickLogout}
>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-log-out-img.png"
alt="logout icon"
className="logout-icon"
/>
</button>
</div>
<div className="nav-menu-mobile">
<ul className="nav-menu-list-mobile">
<Link to="/">
<li className="nav-menu-item-mobile">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-icon.png"
alt="nav home"
className="nav-bar-image"
/>
</li>
</Link>
<Link to="/products">
<li className="nav-menu-item-mobile">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-products-icon.png"
alt="nav products"
className="nav-bar-image"
Venkatesh Athyam
/>
</li>
</Link>
<Link to="/cart">
<li className="nav-menu-item-mobile">
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-cart-icon.png"
alt="nav cart"
className="nav-bar-image"
/>
</li>
</Link>
</ul>
</div>
</nav>
)
}
export default withRouter(Header)
File: src/components/Home
import Cookies from 'js-cookie'
import {Redirect, Link} from 'react-router-dom'
return (
Venkatesh Athyam
<>
<Header />
<div className="home-container">
<div className="home-content">
<h1 className="home-heading">Clothes That Get YOU Noticed</h1>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-img.png"
alt="dresses to be noticed"
className="home-mobile-img"
/>
<p className="home-description">
Fashion is part of the daily air and it does not quite help that it
changes all the time. Clothes have always been a marker of the era
and we are in a revolution. Your fashion makes you been seen and
heard that way you are. So, celebrate the seasons new and exciting
fashion in your own way.
</p>
<Link to="/products">
<button type="button" className="shop-now-button">
Shop Now
</button>
</Link>
</div>
<img
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-home-img.png"
alt="dresses to be noticed"
className="home-desktop-img"
/>
</div>
</>
)
Venkatesh Athyam
}
export default Home
File: src/components/LoginForm
import {Component} from 'react'
import Cookies from 'js-cookie'
import {Redirect} from 'react-router-dom'
import './index.css'
Cookies.set('jwt_token', jwtToken, {
expires: 30,
path: '/',
})
Venkatesh Athyam
history.replace('/')
}
renderPasswordField = () => {
const {password} = this.state
return (
<>
<label className="input-label" htmlFor="password">
PASSWORD
Venkatesh Athyam
</label>
<input
type="password"
id="password"
className="password-input-field"
value={password}
onChange={this.onChangePassword}
/>
</>
)
}
renderUsernameField = () => {
const {username} = this.state
return (
<>
<label className="input-label" htmlFor="username">
USERNAME
</label>
<input
type="text"
id="username"
className="username-input-field"
value={username}
onChange={this.onChangeUsername}
/>
</>
)
}
render() {
const {showSubmitError, errorMsg} = this.state
Venkatesh Athyam
}
export default LoginForm
File: src/components/NotFound
import './index.css'
const apiStatusConstants = {
initial: 'INITIAL',
success: 'SUCCESS',
failure: 'FAILURE',
inProgress: 'IN_PROGRESS',
}
primeDeals: [],
apiStatus: apiStatusConstants.initial,
}
componentDidMount() {
this.getPrimeDeals()
}
}))
this.setState({
primeDeals: updatedData,
apiStatus: apiStatusConstants.success,
})
} else if (response.status === 401) {
this.setState({
apiStatus: apiStatusConstants.failure,
})
}
}
renderPrimeDealsList = () => {
const {primeDeals} = this.state
return (
<div>
<h1 className="primedeals-list-heading">Exclusive Prime Deals</h1>
<ul className="products-list">
{primeDeals.map(product => (
<ProductCard productData={product} key={product.id} />
))}
</ul>
</div>
)
}
renderPrimeDealsFailureView = () => (
<img
src="https://assets.ccbp.in/frontend/react-js/exclusive-deals-banner-img.png"
alt="Register Prime"
className="register-prime-image"
/>
Venkatesh Athyam
renderLoadingView = () => (
<div className="products-loader-container">
<Loader type="ThreeDots" color="#0b69ff" height="50" width="50" />
</div>
)
render() {
const {apiStatus} = this.state
switch (apiStatus) {
case apiStatusConstants.success:
return this.renderPrimeDealsList()
case apiStatusConstants.failure:
return this.renderPrimeDealsFailureView()
case apiStatusConstants.inProgress:
return this.renderLoadingView()
default:
return null
}
}
}
export default PrimeDealsSection
File: src/components/ProductCard
import './index.css'
return (
<li className="product-item">
Venkatesh Athyam
import './index.css'
</div>
</>
)
export default Products
File: src/components/ProductsHeader
import './index.css'
return (
<div className="products-header">
<h1 className="products-list-heading">All Products</h1>
<div className="sort-by-container">
<BsFilterRight className="sort-by-icon" />
<h1 className="sort-by">Sort by</h1>
<select
className="sort-by-select"
value={activeOptionId}
onChange={onChangeSortby}
>
{sortbyOptions.map(eachOption => (
<option
key={eachOption.optionId}
value={eachOption.optionId}
className="select-option"
Venkatesh Athyam
>
{eachOption.displayText}
</option>
))}
</select>
</div>
</div>
)
}
export default ProductsHeader
File: src/components/ProtectedRoute
import './App.css'
Concepts in Focus
• Reconciliation
• Virtual DOM
• React Batch Updating
• setState() Syntax
• Object Syntax
• Callback Syntax
• Object Syntax vs Callback Syntax
• Children Prop
• Passing Text as Children
• Accessing Children
• Controlled vs Uncontrolled Input
• Controlled Input
• Uncontrolled Input
• Props vs State
• State should be minimal
• Keys
• Keys in Lists
Venkatesh Athyam
1. Reconciliation
React compares new virtual DOM with current virtual DOM, and the difference will be efficiently
updated to HTML DOM. So, the Virtual DOM helps to render the UI more performantly.
React only updates what's necessary. This process is known as Reconciliation.
Example:
import { Component } from "react"
Venkatesh Athyam
onIncrement = () => {
this.setState((prevState) => ({ count: prevState.count + 1 }))
this.setState((prevState) => ({ count: prevState.count + 1 }))
this.setState((prevState) => ({ count: prevState.count + 1 }))
}
render() {
const { count } = this.state
console.log("render() called")
return (
<>
<p className="count">Count {count}</p>
<button onClick={this.onIncrement}>Increase</button>
</>
)
}
}
export default Counter
In the above example, the render is called only once as React combines multiple
setState() calls into a single update.
3. setState() Syntax
onIncrement = () => {
this.setState({ count: this.state.count + 1 })
this.setState({ count: this.state.count + 1 })
this.setState({ count: this.state.count + 1 })
}
render() {
const { count } = this.state
return (
<>
<p className="count">Count {count}</p>
<button onClick={this.onIncrement}>Increase</button>
</>
)
}
}
When the HTML button element is clicked, the value of the state variable count is 1.
When the Object Syntax is used, this.state.count is same for every setState statement as setState
is asynchronous.
Callback Syntax:
import { Component } from "react"
onIncrement = () => {
this.setState((prevState) => ({ count: prevState.count + 1 }))
this.setState((prevState) => ({ count: prevState.count + 1 }))
this.setState((prevState) => ({ count: prevState.count + 1 }))
}
render() {
const { count } = this.state
return (
<>
<p className="count">Count {count}</p>
<button onClick={this.onIncrement}>Increase</button>
Venkatesh Athyam
</>
)
}
}
When the HTML button element is clicked, the value of the state variable count is 3.
The setState callback function receive prevState as an argument. So, it will receive an updated state
value when it is executed.
4. Children Prop
The children is a special prop that is automatically passed to every React Component.
The JSX Element/Text included in between the opening and closing tags are considered children.
render() {
const { searchInput } = this.state
return (
<>
<input
type="text"
onChange={this.onChangeSearchInput}
value={searchInput}
/>
<p>{searchInput}</p>
</>
)
}
}
searchInput: event.target.value,
})
}
render() {
const { searchInput } = this.state
return (
<>
<input type="text" onChange={this.onChangeSearchInput} />
<p>{searchInput}</p>
</>
)
}
}
6. Props vs State
• The props and state are plain JS objects.
• The props and state changes trigger the render method.
Props State
Props get passed to the component, similar State is created and managed within the component,
to function parameters similar to a variable declared within the function
Props are used to pass data and event State is used to store the component's data that changes
handlers down to the child components over time
Props are immutable. A component cannot
State should be immutable
change the props
Is
Data Reason
State?
The original list of projects No It is passed as props
The active tab item Yes It changes over time and can't be computed from anything
It can be computed by combining the original list of
The filtered list of projects No
projects with the active tab item
The text decoration of the text -
No It can be derived from the active tab item
Underline
The The color of the text No It can be derived from the active tab item
Venkatesh Athyam
8. Keys
Keys help React identify which items have been changed, added, or removed.
Keys should be given to the elements inside the array to give a stable identity.
const usersList = [
{
uniqueNo: 1,
name: "Rahul",
},
{
uniqueNo: 2,
name: "Praneetha",
},
{
uniqueNo: 3,
name: "Varakumar",
},
]
const listItems = usersList.map((user) => (
<li key={user.uniqueNo}>{user.name}</li>
))
So, React can easily detect what needs to be changed or not, re-rendering only the ones with
changes.
Third-Party Packages
Concepts in Focus
• Third-Party Packages
• Advantages
• Selecting a Third-Party Package
• Third-Party Package
react-player
• React Player Props
• Reference
1. Third-Party Packages
A Third-Party Package is a reusable code developed to perform a specific functionality
1.1 Advantages
• Easy integration
• Saves Time
• More productivity with fewer lines of code
• Better Error Handling
• More Customisation Options ... many more.
We have used many third-party packages like React Router, React Loader, React Icons, JWT, etc.
Node Package Manager contains Third-Party Packages for React JS, Node JS,
Angular JS, and many more libraries and frameworks. To know more about npm you
can refer to this.
Default
Prop Description
Value
playing Set to true or false to pause or play the media false
controls Set to true to display native player controls. false
Set to true to show the video thumbnail, which loads the full player on
light false
click. Pass in an image URL to override the preview image
width Set the width of the player 640px
height Set the height of the player 360px
className Add the custom styles to ReactPlayer -
Example:
File: src/App.js
import './App.css'
File: src/components/VideoPlayer/index.js
import './index.css'
<div className="video-container">
<h1 className="heading">Video Player</h1>
<div className="responsive-container">
<ReactPlayer url={videoURL} />
</div>
</div>
)
import './index.css'
onClickPlay = () => {
this.setState(prevState => ({isPlaying: !prevState.isPlaying}))
}
render() {
const {isPlaying} = this.state
const btnText = isPlaying ? 'Pause' : 'Play'
return (
<div className="video-container">
Venkatesh Athyam
Reference
To know more about react-player , you can refer to this.
Concepts in Focus
• Third-Party Package
recharts
• Advantages
• Bar Chart
• Components in Bar Chart
• ResponsiveContainer
• XAxis
• YAxis
• Legend
• Bar
• Pie Chart
• Components in Pie Chart
• Pie
• Cell
• Reference
• Area
• Bar
• Line, etc.
Polar:
• Pie
• Radar
• Radial Bar
Installation Command:
2. Bar Chart
import {
BarChart,
Bar,
XAxis,
YAxis,
Legend,
ResponsiveContainer,
} from "recharts"
const data = [
{
group_name: "Group A",
boys: 200,
girls: 400,
},
{
group_name: "Group B",
boys: 3000,
girls: 500,
},
{
group_name: "Group C",
boys: 1000,
girls: 1500,
},
{
group_name: "Group D",
Venkatesh Athyam
boys: 700,
girls: 1200,
},
]
return (
<ResponsiveContainer width="100%" height={500}>
<BarChart
data={data}
margin={{
top: 5,
}}
>
<XAxis
dataKey="group_name"
tick={{
stroke: "gray",
strokeWidth: 1,
}}
/>
<YAxis
tickFormatter={DataFormatter}
tick={{
stroke: "gray",
strokeWidth: 0,
}}
/>
<Legend
wrapperStyle={{
padding: 30,
}}
/>
<Bar dataKey="boys" name="Boys" fill="#1f77b4" barSize="20%" />
<Bar dataKey="girls" name="Girls" fill="#fd7f0e" barSize="20%" />
</BarChart>
</ResponsiveContainer>
)
}
Output :
Venkatesh Athyam
3.1 ResponsiveContainer
It is a container Component to make charts adapt to the size of the parent container.
Props:
We can provide different props to the ReactJS ResponsiveContainer Component. Below are some
of the most commonly used props.
Note:
3.2 XAxis
The XAxis Component represents the X-Axis of a Chart.
Props:
We can provide different props to the ReactJS XAxis Component. Below are some of the most
commonly used props.
Example - tickFormatter:
If we want to show the thousands in the form of k on the tick, the formatter function would be:
3.3 Yaxis
3.4 Legend
The Legend Component represents the legend of a Chart.
By default, the content of the legend is generated by the name of Line,Bar, Area, etc. If no name has
been set, the prop dataKeyis used to generate the content of the legend.
Props:
We can provide different props to the ReactJS Legend Component. Below are some of the most
commonly used props.
3.5 Bar
The Bar Component represents a bar in the Chart.
Props:
We can provide different props to the ReactJS Bar Component. Below are some of the most
commonly used props.
Note:
The value of the prop name is used in tooltip and legend to represent a bar/pie. If no value was set,
the value of dataKey will be used alternatively.
4. PieChart
The PieChart Component represents the container of the Pie Chart.
Example:
import { PieChart, Pie, Legend, Cell, ResponsiveContainer } from "recharts"
const data = [
{
count: 809680,
language: "Telugu",
},
{
count: 4555697,
language: "Hindi",
},
{
count: 12345657,
language: "English",
},
]
<Legend
iconType="circle"
layout="vertical"
verticalAlign="middle"
align="right"
/>
</PieChart>
</ResponsiveContainer>
)
}
export default App
5.1 Pie
The Pie Component represents a pie in the Chart.
Props:
We can provide different props to the ReactJS Pie Component. Below are some of the most
commonly used props.
Note:
If a percentage is set to the props innerRadius or outerRadius, the final value is obtained
by multiplying the percentage of maxRadius which is calculated by the
width, height, cx , and cy .
5.2 Cell
The Cell Component represents the cell of a Chart.
It can be wrapped by a Pie , Bar, or RadialBarComponents to specify the attributes of each child.
Props:
We can provide different props to the ReactJS Cell Component. Below are some of the most
commonly used props.
Note:
The ResponsiveContainer and Legend Components in Pie Chart are similar to the
Components in Bar Chart.
6. Reference
To know more about the recharts , you can refer to this.
Concepts in Focus
• Third-Party Package
react-chrono
• Advantages
• Chrono Props
• mode
Venkatesh Athyam
• items
• theme
• Rendering Custom Content
• Reference
1.1 Advantages
• Can render the timelines in three different modes (horizontal, vertical, and tree).
• Can autoplay the timeline with slideshow mode.
• Can navigate the timeline via keyboard.
2. Chrono Props
We can provide different props to the ReactJS Chrono component. Below are some of the most
commonly used props.
2.1 mode
Example:
<Chrono mode="VERTICAL" />
2.2 items
The items prop is used to build the timeline. It is a collection of the Timeline Item Model.
Timeline Item Model is an object consist of the given properties:
Example:
.chrono-container {
width: 500px;
height: 400px;
}
import {Chrono} from 'react-chrono'
const items = [
{
title: 'May 1940',
cardTitle: 'Dunkirk',
cardSubtitle: 'Men of the British Expeditionary Force.',
cardDetailedText:
'On 10 May 1940, Hitler began his long-awaited offensive in the west by invading neutral
Holland and attacking northern France.',
},
]
Warning:
If any property misses in the Timeline Item Model, the respective value won't be
displayed in the timeline item.
Note:
The Chrono Component should be wrapped in a container that has a width and height.
2.3 theme
The colors can be customized with the theme prop.
Example:
<Chrono
theme={{
primary: "red",
secondary: "blue",
Venkatesh Athyam
cardBgColor: "yellow",
cardForeColor: "violet",
titleColor: "red",
}}
/>
.image {
width: 200px;
height: 200px;
}
import {Chrono} from 'react-chrono'
Output:
Each HTML div element is automatically converted into a timeline item and inserted into the
timeline card.
Venkatesh Athyam
Venkatesh Athyam
Note:
The items prop is optional and custom rendering is supported on all three modes.
Example:
The below example will set the title for the custom contents.
.chrono-container {
width: 400px;
height: 600px;
}
.image {
width: 200px;
height: 200px;
}
4. Reference
To know more about the react-chrono , you can refer to this.
Venkatesh Athyam
Concepts in Focus
• Third-Party Package
react-slick
• Advantages
• Slider Props
• Reference
1.1 Advantages
• Easy to use
• Highly customizable
• More performant
2. Slider Props
We can provide different props to the Slider component. Below are the most commonly used props.
Example:
File: src/components/ReactSlick/index.js
import Slider from 'react-slick'
import 'slick-carousel/slick/slick.css'
Venkatesh Athyam
import 'slick-carousel/slick/slick-theme.css'
import './index.css'
background-color: #419be0;
padding: 40px;
}
File: src/App.js
import ReactSlick from './components/ReactSlick'
Reference
To know more about the react-slick , you can refer to this.
Concepts in Focus
• Third-Party Package
reactjs-popup
• Advantages
• ReactJS Popup Props
• Reference
1.1 Advantages
• ReactJS provides Modal, Tooltip, and Menu
• Provides Support for controlled Modals & Tooltips
Default
Prop Description
Value
Represents the element to be rendered in-place where the Popup is JSX
trigger
defined element
When set to true, Popup content will be displayed as a modal on the
modal false
trigger of Popup. If not tooltip will be displayed
Defines the position of the tooltip. It can be one of 'top left', 'top right', bottom
position
'bottom right', 'bottom left' center
open Defines the state of Popup. Whether it is opened or not false
overlayStyle Custom overlay style object
import 'reactjs-popup/dist/index.css'
import './index.css'
>
<div>
<p>React is a popular and widely used programming language</p>
</div>
</Popup>
</div>
)
export default ReactPopUp
File: src/components/ReactPopup/index.css
.trigger-button {
font-size: 16px;
font-weight: 400;
font-family: 'Roboto';
color: white;
padding: 8px 15px 8px 15px;
margin: 8px;
background-color: #7c69e9;
border: none;
border-radius: 4px;
outline: none;
}
.popup-container {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
File: src/App.js
import ReactPopup from './components/ReactPopup'
</button>
}
>
{close => (
<>
<div>
<p>React is a popular and widely used programming language</p>
</div>
<button
type="button"
className="trigger-button"
onClick={() => close()}
>
Close
</button>
</>
)}
</Popup>
</div>
)
export default ReactPopUp
Venkatesh Athyam
)
export default ReactPopUp
Reference
To know more about the reactjs-popup , you can refer to this.
React Context
Concepts in Focus
• Prop Drilling
• React Context
• Creating Context
• Context Properties
• How to Access the Value?
• Consumer Component
• Understanding Syntax
• Windows App Example
• Initial Code
• Final Code
• Google Translator
1. Prop Drilling
Props are passed from one Component to another Component that does not need the data but only
helps in passing it through the tree is called Prop Drilling.
Venkatesh Athyam
2. React Context
Context is a mechanism that provides different Components and allows us to pass data without
doing prop drilling.
3. Consumer Component
Syntax:
<ContextObject.Consumer>
{/*callback function*/}
</ContextObject.Consumer>
• We access the Consumer component using dot notation from the context object
.
• We will give a callback function as children for Consumer Component.
Venkatesh Athyam
5. Google Translator
• In the Windows App example, we are using three different languages to display the text.
• You can translate one language to another language using google translator.
• Check google translator website here .
Concepts in Focus
• Provider
• Syntax
• Context Flow For Windows App
• Best Practice
• Final Code
Venkatesh Athyam
1. Provider
• Provider Component updates the value of Context.
• When the provider updates context, all the nested consumers of that provider will be re-
rendered.
• Updated context value can only be accessed by the consumers nested within the provider.
<ContextObject.Provider value={/* some value */}>
...
<ContextObject.Provider/>
To update context value, we have to pass it as a prop to the Provider omponent.
3. Best Practice
• The context value should have the data which the consumers need.
• It should also contain the required methods to update that data.
4.Final Code
File: src/App.js
import {Component} from 'react'
import './App.css'
render() {
const {activeLanguage} = this.state
return (
<LanguageContext.Provider
value={{activeLanguage, changeLanguage: this.changeLanguage}}
>
<Header />
<LandingSection />
<FeaturesSection />
</LanguageContext.Provider>
)
}
}
export default App
File: src/context/LanguageContext.jsx
import React from 'react'
import './index.css'
import './index.css'
const langOptions = [
{id: 1, value: 'EN', language: 'English'},
return (
<nav className="nav-header">
<img
className="website-logo"
src="https://assets.ccbp.in/frontend/react-js/windows-logo-img.png"
alt="website logo"
/>
<select
className="language-dropdown"
value={activeLanguage}
onChange={onChangeLanguage}
>
{langOptions.map(eachOption => (
<option key={eachOption.id} value={eachOption.value}>
{eachOption.language}
</option>
))}
</select>
</nav>
)
}}
</LanguageContext.Consumer>
)
export default Header
File: src/components/LandingSection/index.js
import LanguageContext from '../../context/LanguageContext'
import './index.css'
const landingSectionContent = {
Venkatesh Athyam
EN: {
heading: 'Windows 11',
description:
'Windows 11 provides a calm and creative space where you can pursue your passions through a
fresh experience. From a rejuvenated Start menu to new ways to connect to your favorite people,
news, games, and content. Windows is the place to think, express, and create in a natural way.',
},
HI: {
description:
description:
case 'TE':
return landingSectionContent.TE
default:
return null
}
}
return (
<LanguageContext.Consumer>
{value => {
const {activeLanguage} = value
const {heading, description} = getLandingSectionData(activeLanguage)
return (
<div className="bg-container">
<div className="responsive-container">
<div className="description-container">
<h1 className="heading">{heading}</h1>
<p className="description">{description}</p>
</div>
<img
className="logo-white"
src="https://assets.ccbp.in/frontend/react-js/windows-logo-white-img.png"
alt="windows logo"
/>
</div>
</div>
)
}}
</LanguageContext.Consumer>
)
}
export default LandingSection
File: src/components/NewWaysToConnect/index.js
Venkatesh Athyam
import './index.css'
const newWaysToConnectContent = {
EN: {
heading: 'New ways to connect',
description:
'Connect instantly to the people you care about right from your desktop with Microsoft Teams.
Call or chat for free, no matter what device they’re on.',
},
HI: {
description:
description:
'మైక్రోసాఫ్ట్ బృందాలతో మీ డెస్క్టాప్ నుండి మీరు శ్రద్ధ వహించే వ్యక్తు లతో తక్షణమే కనెక్ట్ అవ్వండి.
అవి ఏ పరికరంలో ఉన్నా సరే ఉచితంగా కాల్ చేయండి లేదా చాట్ చేయండి',
},
}
return newWaysToConnectContent.HI
case 'TE':
return newWaysToConnectContent.TE
default:
return null
}
}
return (
<LanguageContext.Consumer>
{value => {
const {activeLanguage} = value
const {heading, description} = getNewWaysToConnectData(activeLanguage)
return (
<div className="new-ways-to-connect-container">
<h1 className="new-ways-to-content-heading">{heading}</h1>
<p className="new-ways-to-content-description">{description}</p>
</div>
)
}}
</LanguageContext.Consumer>
)
}
export default NewWaysToConnect
File: src/components/Playtime/index.js
import './index.css'
const playtimeContent = {
EN: {
heading: 'Playtime. Anytime',
Venkatesh Athyam
description:
'Windows takes gaming to a whole new level with graphic capabilities that rival reality.
Discover your next favorite game with Xbox GamePass, giving you access to over 100 high-quality
games.',
},
HI: {
description:
description:
'రియాలిటీకి ప్రత్యర్థిగా ఉండే గ్రాఫిక్ సామర్థ్యాలతో విండోస్ గేమింగ్ను సరికొత్త స్థా యికి
తీసుకువెళుతుంది . మీ తదుపరి ఇష్టమైన ఆటను ఎక్స్బాక్స్ గేమ్పాస్తో కనుగొనండి, మీకు 100 కి
పైగా అధిక-నాణ్యత ఆటలకు ప్రాప్యతను ఇస్తుంది.',
},
}
}
}
return (
<LanguageContext.Consumer>
{value => {
const {activeLanguage} = value
const {heading, description} = getPlaytimeData(activeLanguage)
return (
<div className="playtime-container">
<h1 className="playtime-heading">{heading}</h1>
<div className="playtime-description-container">
<p className="playtime-description">{description}</p>
<img
className="playtime-games-image"
src="https://assets.ccbp.in/frontend/react-js/gaming-pad-img.png"
alt="gaming pad"
/>
</div>
</div>
)
}}
</LanguageContext.Consumer>
)
}
export default Playtime
Concepts in Focus
• Context
• Using Context in methods
• Final Code
1. Context
Context can also be used:
Venkatesh Athyam
import "./index.css";
const apiStatusConstants = {
initial: "INITIAL",
success: "SUCCESS",
failure: "FAILURE",
inProgress: "IN_PROGRESS",
};
apiStatus: apiStatusConstants.initial,
quantity: 1,
};
componentDidMount() {
this.getProductData();
}
this.setState({
apiStatus: apiStatusConstants.inProgress,
});
const jwtToken = Cookies.get("jwt_token");
const apiUrl = `https://apis.ccbp.in/products/${id}`;
const options = {
headers: {
Venkatesh Athyam
renderLoadingView = () => (
<div className="products-details-loader-container">
<Loader type="ThreeDots" color="#0b69ff" height="50" width="50" />
</div>
);
renderFailureView = () => (
<div className="product-details-error-view-container">
Venkatesh Athyam
<img
alt="error view"
src="https://assets.ccbp.in/frontend/react-js/nxt-trendz-error-view-img.png"
className="error-view-image"
/>
<h1 className="product-not-found-heading">Product Not Found</h1>
<button type="button" className="button">
Continue Shopping
</button>
</div>
);
onDecrementQuantity = () => {
const { quantity } = this.state;
if (quantity > 1) {
this.setState((prevState) => ({ quantity: prevState.quantity - 1 }));
}
};
onIncrementQuantity = () => {
this.setState((prevState) => ({ quantity: prevState.quantity + 1 }));
};
renderProductDetailsView = () => (
<CartContext.Consumer>
{(value) => {
const { productData, quantity, similarProductsData } = this.state;
const {
availability,
brand,
description,
imageUrl,
Venkatesh Athyam
price,
rating,
title,
totalReviews,
} = productData;
const { addCartItem } = value;
const onClickAddToCart = () => {
addCartItem({ ...productData, quantity });
};
return (
<div className="product-details-success-view">
<div className="product-details-container">
<img src={imageUrl} alt="product" className="product-image" />
<div className="product">
<h1 className="product-name">{title}</h1>
<p className="price-details">Rs {price}/-</p>
<div className="rating-and-reviews-count">
<div className="rating-container">
<p className="rating">{rating}</p>
<img
src="https://assets.ccbp.in/frontend/react-js/star-img.png"
alt="star"
className="star"
/>
</div>
<p className="reviews-count">{totalReviews} Reviews</p>
</div>
<p className="product-description">{description}</p>
<div className="label-value-container">
<p className="label">Available:</p>
<p className="value">{availability}</p>
Venkatesh Athyam
</div>
<div className="label-value-container">
<p className="label">Brand:</p>
<p className="value">{brand}</p>
</div>
<hr className="horizontal-line" />
<div className="quantity-container">
<button
type="button"
className="quantity-controller-button"
onClick={this.onDecrementQuantity}
>
<BsDashSquare className="quantity-controller-icon" />
</button>
<p className="quantity">{quantity}</p>
<button
type="button"
className="quantity-controller-button"
onClick={this.onIncrementQuantity}
>
<BsPlusSquare className="quantity-controller-icon" />
</button>
</div>
<button
type="button"
className="button add-to-cart-btn"
onClick={onClickAddToCart}
>
ADD TO CART
</button>
</div>
</div>
Venkatesh Athyam
renderProductDetails = () => {
const { apiStatus } = this.state;
switch (apiStatus) {
case apiStatusConstants.success:
return this.renderProductDetailsView();
case apiStatusConstants.failure:
return this.renderFailureView();
case apiStatusConstants.inProgress:
return this.renderLoadingView();
default:
return null;
}
};
render() {
return (
Venkatesh Athyam
<>
<Header />
<div className="product-item-details-container">
{this.renderProductDetails()}
</div>
</>
);
}
}
export default ProductItemDetails;
3. Final code
Run the below command in your IDE to download the final code.
ccbp start RJSIVIJ1YR
Concepts in Focus
• Deploying the Ecommerce Application Code
• Ecommerce Application-Final Code
Warning:
An error will be thrown if you are trying to publish with the already existing URL.
Note:
Styled Components
Concepts in Focus
• Styling React Components
• Using CSS
• CSS-in-JS
• Styled Components
• Installation
• Syntax
• Importing styled
• Creating and Exporting Styled Component
• Importing and Rendering Styled Component
• Adapting based on props
• Modularity of Code
• Conditional Styling using Props
• Advantages of Styled Components
• Unique Class Names
• Elimination of dead styles
• Dynamic Styling
• Can differentiate between the types of props they receive
• Easier Debugging
• Global Styling
• Extending Styles
• The "as" prop
• Boolean Attribute
File: src/App.css
.heading {
color: #0070c1;
font-family: 'Roboto';
}
1.2 CSS-in-JS
CSS-in-JS is a styling technique where JavaScript is used to style React Components. It can be
implemented using the below third party packages.
• Styled Components
• Emotion
• Radium many more...
2. Styled Components
Styled Components are one of the new ways to use CSS in modern JavaScript. Components are
used to reuse code, similarly Styled Components are used to reuse styles.
2.1 Installation
npm install styled-components
2.2 Syntax
const StyledComponentName = styled.tagName`
property1: value1;
property2: value2;
...
`;
Note:
Syntax:
File: src/styledComponents.js
The color and bgColor are the part of styling, instead of passing them as props, we can passthe type
of button to handle styles in styled components.
Example:
File: src/App.js
import "./App.css";
import { CustomButton } from "./styledComponents";
File: src/styledComponents.js
Venkatesh Athyam
File:src/App.js
import "./App.css";
import { CustomButton } from "./styledComponents";
You’ll notice, though, that we haven’t given our button a type in the above code snippet. Let’s do
that:
File:src/App.js
import "./App.css";
import { CustomButton } from "./styledComponents";
Styled components can differentiate between the types of props they receive. They know that type is
an HTML attribute, so they render
<button type="button">Click</button>, while using the outline prop in their own processing.
Notice how we attached an event handler, too?
Venkatesh Athyam
It also allows you to see the component's displayName in React DevTools. For example, consider
writing a styled component that renders a button element, called CustomButton. It will normally
show up in DevTools as styled.button, but with the displayName option enabled, it has the name
you gave it CustomButton.
This makes it easier to find your components and to figure out where they live in your app.
• For more info, you can go through this link here.
Note:
babel: {
plugins: [
[
"babel-plugin-styled-components",
{
fileName: false,
},
],
],
},
};
It is already configured.
File: src/App.js
4. Extending Styles
• Frequently you might want to use a component, but change it slightly for a single case. Now,
you could pass in a function and change them based on some props, but that's quite a lot of
effort for overriding the styles once.
• To easily make a new component that inherits the styling of another, just wrap it in
the styled(). Here we use the CustomButton and create a special one, extending it with
some color-related styling.
Note:
File:src/styledComponents.js
import styled from "styled-components";
• This sort of thing is very useful in use cases like a navigation bar where some of the items
should be links and some just buttons, but all be styled the same way.
6. Boolean Attribute
• The Presence of boolean attribute is taken as true no need to specify the value again.
• The absence of boolean attribute is taken as false.
import "./App.css";
import { CustomButton } from "./styledComponents";