Week5 FSD
Week5 FSD
4.4 REACT
function Hello(props) {
return <h1>Hello World!</h1>;
}
Open your terminal in the directory you would like to create your application.
npx create-react-app my-react-app. create-react-app will set up everything you need to run a
React application.
cd my-react-app
Run this command to execute the React application my-react-app:
npm start
A new browser window will pop up with your newly created React App! If not, open your browser
and type localhost:3000 in the address bar.
Week5_Day2_Session1
4.5 JSX
JSX stands for JavaScript XML. JSX allows us to write HTML in React. JSX makes it easier to
write and add HTML in React. JSX allows us to write HTML elements in JavaScript and place them
in the DOM without any createElement() and/or appendChild() methods. JSX converts HTML tags
into react elements. You are not required to use JSX, but JSX makes it easier to write React
applications.
Example 1
JSX:
Example 2
Without JSX:
As you can see in the first example, JSX allows us to write HTML directly within the JavaScript code.
JSX is an extension of the JavaScript language based on ES6, and is translated into regular
JavaScript at runtime.
Expressions in JSX
With JSX you can write expressions inside curly braces { }. The expression can be a React variable,
or property, or any other valid JavaScript expression. JSX will execute the expression and return
the result:
Example
Execute the expression 5 + 5:
Example
Create a list with three list items:
const myElement = (
<ul>
<li>Apples</li>
<li>Bananas</li>
<li>Cherries</li>
</ul>
);
Example
Wrap two paragraphs inside one DIV element:
const myElement = (
<div>
<p>I am a paragraph.</p>
<p>I am a paragraph too.</p>
</div>
);
JSX will throw an error if the HTML is not correct, or if the HTML misses a parent element.
Alternatively, you can use a "fragment" to wrap multiple lines. This will prevent unnecessarily
adding extra nodes to the DOM.
Example
Wrap two paragraphs inside a fragment:
const myElement = (
<>
<p>I am a paragraph.</p>
<p>I am a paragraph too.</p>
</>
);
Use attribute className instead. JSX solved this by using className instead. When JSX is
rendered, it translates className attributes into class attributes.
Example
Use attribute className instead of class in JSX:
Conditions - if statements
React supports if statements, but not inside JSX.
To be able to use conditional statements in JSX, you should put the if statements outside of the
JSX, or you could use a ternary expression instead:
Option 1:
Write if statements outside of the JSX code:
Example
Write "Hello" if x is less than 10, otherwise "Goodbye":
const x = 5;
let text = "Goodbye";
if (x < 10) {
text = "Hello";
}
Option 2:
Use ternary expressions instead:
Example
Write "Hello" if x is less than 10, otherwise "Goodbye":
const x = 5;
Note that in order to embed a JavaScript expression inside JSX, the JavaScript must be wrapped
with curly braces, {}.
It is called JSX, and it is a syntax extension to JavaScript. We recommend using it with React to
describe what the UI should look like. JSX may remind you of a template language, but it comes
with the full power of JavaScript.
JSX produces React “elements”. We will explore rendering them to the DOM in the next section.
Below, you can find the basics of JSX necessary to get you started.
Why JSX?
React embraces the fact that rendering logic is inherently coupled with other UI logic: how events
are handled, how the state changes over time, and how the data is prepared for display.
Instead of artificially separating technologies by putting markup and logic in separate files, React
separates concerns with loosely coupled units called “components” that contain both. We will
come back to components in a further section, but if you’re not yet comfortable putting markup
in JS, this talk might convince you otherwise.
React doesn’t require using JSX, but most people find it helpful as a visual aid when working with
UI inside the JavaScript code. It also allows React to show more useful error and warning messages.
With that out of the way, let’s get started!
In the example below, we embed the result of calling a JavaScript function, formatName(user),
into an <h1> element.
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'Harper',
lastName: 'Perez'
};
const element = (
<h1>
Hello, {formatName(user)}!
</h1>
);
Try it on CodePen
We split JSX over multiple lines for readability. While it isn’t required, when doing this, we also
recommend wrapping it in parentheses to avoid the pitfalls of automatic semicolon insertion.
This means that you can use JSX inside of if statements and for loops, assign it to variables, accept
it as arguments, and return it from functions:
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}
Warning:
Since JSX is closer to JavaScript than to HTML, React DOM uses camelCase property naming
convention instead of HTML attribute names.
For example, class becomes className in JSX, and tabindex becomes tabIndex.
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);
Rendering Elements
In React, Render is the technique that can redirect a page with the help of function render(). Most
importantly, render a function we can use to define the HTML code within the HTML element. It
helps to display certain views in the UI using certain logic defined in the render function and
returns the output.
Before React, Developers directly manipulated the DOM elements which resulted in frequent
DOM manipulation, and each time an update was made the browser had to recalculate and
repaint the whole view according to the particular CSS of the page, which made the total
process to consume a lot of time. As a betterment, React brought into the scene the virtual
DOM. The Virtual DOM can be referred to as a copy of the actual DOM representation that is
used to hold the updates made by the user and finally reflect it over to the original Browser
DOM at once consuming much lesser time.
What is ReactDOM?
ReactDOM is a package that provides DOM specific methods that can be used at the top level
of a web app to enable an efficient way of managing DOM elements of the web page.
ReactDOM provides the developers with an API containing the following methods and a few
more.
• render()
• findDOMNode()
• unmountComponentAtNode()
• hydrate()
• createPortal()
Pre-requisite: To use the ReactDOM in any React web app we must first import ReactDOM
from the react-dom package by using the following code snippet:
import ReactDOM from 'react-dom'
render() Function
This is one of the most important methods of ReactDOM. This function is used to render a
single React Component or several Components wrapped together in a Component or a div
element. This function uses the efficient methods of React for updating the DOM by being
able to change only a subtree, efficient diff methods, etc.
Syntax:
ReactDOM.render(element, container, callback)
Parameters: This method can take a maximum of three parameters as described below.
• element: This parameter expects a JSX expression or a React Element to be rendered.
• container: This parameter expects the container in which the element has to be rendered.
• callback: This is an optional parameter that expects a function that is to be executed once
the render is complete.
Return Type: This function returns a reference to the component or null if a stateless
component was rendered.
findDOMNode() Function
This function is generally used to get the DOM node where a particular React component was
rendered. This method is very less used like the following can be done by adding a ref
attribute to each component itself.
Syntax:
ReactDOM.findDOMNode(component)
Parameters: This method takes a single parameter component that expects a React
Component to be searched in the Browser DOM.
Return Type: This function returns the DOM node where the component was rendered on
success otherwise null.
unmountComponentAtNode() Function
This function is used to unmount or remove the React Component that was rendered to a
particular container. As an example, you may think of a notification component, after a brief
amount of time it is better to remove the component making the web page more efficient.
Syntax:
ReactDOM.unmountComponentAtNode(container)
Parameters: This method takes a single parameter container which expects the DOM
container from which the React component has to be removed.
Return Type: This function returns true on success otherwise false.
hydrate() Function
This method is equivalent to the render() method but is implemented while using server-side
rendering.
Syntax:
ReactDOM.hydrate(element, container, callback)
Parameters: This method can take a maximum of three parameters as described below.
• element: This parameter expects a JSX expression or a React Component to be rendered.
• container: This parameter expects the container in which the element has to be rendered.
• callback: This is an optional parameter that expects a function that is to be executed once
the render is complete.
Return Type: This function attempts to attach event listeners to the existing markup and
returns a reference to the component or null if a stateless component was rendered.
createPortal() Function
Usually, when an element is returned from a component’s render method, it’s mounted on the
DOM as a child of the nearest parent node which in some cases may not be desired. Portals
allow us to render a component into a DOM node that resides outside the current DOM
hierarchy of the parent component.
Syntax:
ReactDOM.createPortal(child, container)
Parameters: This method takes two parameters as described below.
• child: This parameter expects a JSX expression or a React Component to be rendered.
• container: This parameter expects the container in which the element has to be rendered.
Return Type: This function returns nothing.
Rendering an Element in React: In order to render any element into the Browser DOM, we
need to have a container or root DOM element. It is almost a convention to have a div
element with the id=”root” or id=”app” to be used as the root DOM element. Let’s suppose
our index.html file has the following statement inside it.
<div id="root"></div>
Filename App.js: Now, in order to render a simple React Element to the root node, we must
write the following in the App.js file.
• javascript
import React,{ Component } from 'react';
render() {
return (
<div>
<h1>Welcome to GeeksforGeeks!</h1>
</div>
);
Output:
Now, you have created your first ever React Element and also have rendered it in place, but
React was not developed to create static pages, the intention of using React is to create a
more logical and active webpage. In order to do so, we will need to update the elements. This
next section will guide us through the same.
Updating an Element in React: React Elements are immutable i.e. once an element is created
it is impossible to update its children or attribute. Thus, in order to update an element, we
must use the render() method several times to update the value over time. Let’s see this in an
example.
• javascript
function showTime()
{
const myElement = (
<div>
<h1>Welcome to GeeksforGeeks!</h1>
<h2>{new Date().toLocaleTimeString()}</h2>
</div>
);
ReactDOM.render(
myElement,
document.getElementById("root")
);
setInterval(showTime, 1000);
Output:
In the above example, we have created a function showTime() that displays the current time,
and we have set an interval of 1000ms or 1 sec that recalls the function each second thus
updating the time in each call. For simplicity, we have only shown the timespan of one second
in the given image.
React Render Efficiency: React is chosen over the legacy of DOM update because of its
increased efficiency. React achieves this efficiency by using the virtual DOM and efficient
differentiating algorithm. In the example of displaying the current time, at each second we call
the render method, and the virtual DOM gets updated and then the differentiator checks for
the particular differences in Browser DOM and the Virtual DOM and then updates only what is
required such as in the given example the time is the only thing that is getting changed each
time not the title “Welcome to GeeksforGeeks!” thus React only updates the time itself making
it much more efficient than conventional DOM manipulation.
Note:
One might confuse elements with a more widely known concept of “components”. We will
introduce components in the next section. Elements are what components are “made of”, and we
encourage you to read this section before jumping ahead.
<div id="root"></div>
We call this a “root” DOM node because everything inside it will be managed by React DOM.
Applications built with just React usually have a single root DOM node. If you are integrating React
into an existing app, you may have as many isolated root DOM nodes as you like.
To render a React element, first pass the DOM element to ReactDOM.createRoot(), then pass the
React element to root.render():
With our knowledge so far, the only way to update the UI is to create a new element, and pass it
to root.render().
function tick() {
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
root.render(element);
}
setInterval(tick, 1000);
Try it on CodePen
It calls root.render() every second from a setInterval() callback. In practice, most React apps only
call root.render() once. In the next sections we will learn how such code gets encapsulated into
stateful components. We recommend that you don’t skip topics because they build on each other.
Even though we create an element describing the whole UI tree on every tick, only the text node
whose contents have changed gets updated by React DOM.
In our experience, thinking about how the UI should look at any given moment, rather than how
to change it over time, eliminates a whole class of bugs.
ReactDOM
The react-dom package provides DOM-specific methods that can be used at the top level of your
app and as an escape hatch to get outside the React model if you need to.
react-dom/client
react-dom/server
Overview
The react-dom package exports these methods:
createPortal()
flushSync()
These react-dom methods are also exported, but are considered legacy:
render()
hydrate()
findDOMNode()
unmountComponentAtNode()
Both render and hydrate have been replaced with new client methods in React 18. These methods
will warn that your app will behave as if it’s running React 17.
Browser Support
React supports all modern browsers, although some polyfills are required for older versions.
We do not support older browsers that don’t support ES5 methods or microtasks such as Internet
Explorer. You may find that your apps do work in older browsers if polyfills such as es5-shim and
es5-sham are included in the page, but you’re on your own if you choose to take this path.
Reference
createPortal()
createPortal(child, container)
Creates a portal. Portals provide a way to render children into a DOM node that exists outside the
hierarchy of the DOM component.
flushSync()
flushSync(callback)
Force React to flush any updates inside the provided callback synchronously. This ensures that the
DOM is updated immediately.
flushSync may force pending Suspense boundaries to show their fallback state.
flushSync may also run pending effects and synchronously apply any updates they contain before
returning.
flushSync may also flush updates outside the callback when necessary to flush the updates inside
the callback. For example, if there are pending updates from a click, React may flush those before
flushing the updates inside the callback.
Legacy Reference
render()
render(element, container[, callback])
Note:
render has been replaced with createRoot in React 18. See createRoot for more info.
Render a React element into the DOM in the supplied container and return a reference to the
component (or returns null for stateless components).
If the React element was previously rendered into container, this will perform an update on it and
only mutate the DOM as necessary to reflect the latest React element.
If the optional callback is provided, it will be executed after the component is rendered or updated.
render() controls the contents of the container node you pass in. Any existing DOM elements
inside are replaced when first called. Later calls use React’s DOM diffing algorithm for efficient
updates.
render() does not modify the container node (only modifies the children of the container). It may
be possible to insert a component to an existing DOM node without overwriting the existing
children.
render() currently returns a reference to the root ReactComponent instance. However, using this
return value is legacy and should be avoided because future versions of React may render
components asynchronously in some cases. If you need a reference to the root ReactComponent
instance, the preferred solution is to attach a callback ref to the root element.
hydrate()
hydrate(element, container[, callback])
Note:
hydrate has been replaced with hydrateRoot in React 18. See hydrateRoot for more info.
Same as render(), but is used to hydrate a container whose HTML contents were rendered by
ReactDOMServer. React will attempt to attach event listeners to the existing markup.
React expects that the rendered content is identical between the server and the client. It can patch
up differences in text content, but you should treat mismatches as bugs and fix them. In
development mode, React warns about mismatches during hydration. There are no guarantees
that attribute differences will be patched up in case of mismatches. This is important for
performance reasons because in most apps, mismatches are rare, and so validating all markup
would be prohibitively expensive.
If a single element’s attribute or text content is unavoidably different between the server and the
client (for example, a timestamp), you may silence the warning by adding
suppressHydrationWarning={true} to the element. It only works one level deep, and is intended
to be an escape hatch. Don’t overuse it. Unless it’s text content, React still won’t attempt to patch
it up, so it may remain inconsistent until future updates.
If you intentionally need to render something different on the server and the client, you can do a
two-pass rendering. Components that render something different on the client can read a state
variable like this.state.isClient, which you can set to true in componentDidMount(). This way the
initial render pass will render the same content as the server, avoiding mismatches, but an
additional pass will happen synchronously right after hydration. Note that this approach will make
your components slower because they have to render twice, so use it with caution.
Remember to be mindful of user experience on slow connections. The JavaScript code may load
significantly later than the initial HTML render, so if you render something different in the client-
only pass, the transition can be jarring. However, if executed well, it may be beneficial to render a
“shell” of the application on the server, and only show some of the extra widgets on the client. To
learn how to do this without getting the markup mismatch issues, refer to the explanation in the
previous paragraph.
unmountComponentAtNode()
unmountComponentAtNode(container)
Remove a mounted React component from the DOM and clean up its event handlers and state. If
no component was mounted in the container, calling this function does nothing. Returns true if a
component was unmounted and false if there was no component to unmount.
findDOMNode()
findDOMNode is an escape hatch used to access the underlying DOM node. In most cases, use of
this escape hatch is discouraged because it pierces the component abstraction. It has been
deprecated in StrictMode.
findDOMNode(component)
If this component has been mounted into the DOM, this returns the corresponding native browser
DOM element. This method is useful for reading values out of the DOM, such as form field values
and performing DOM measurements. In most cases, you can attach a ref to the DOM node and
avoid using findDOMNode at all.
When a component renders to null or false, findDOMNode returns null. When a component
renders to a string, findDOMNode returns a text DOM node containing that value. As of React 16,
a component may return a fragment with multiple children, in which case findDOMNode will
return the DOM node corresponding to the first non-empty child.
findDOMNode only works on mounted components (that is, components that have been placed
in the DOM). If you try to call this on a component that has not been mounted yet (like calling
findDOMNode() in render() on a component that has yet to be created) an exception will be
thrown.
This approach enables the declarative API of React: You tell React what state you want the UI to
be in, and it makes sure the DOM matches that state. This abstracts out the attribute manipulation,
event handling, and manual DOM updating that you would otherwise have to use to build your
app.
Since “virtual DOM” is more of a pattern than a specific technology, people sometimes say it to
mean different things. In React world, the term “virtual DOM” is usually associated with React
elements since they are the objects representing the user interface. React, however, also uses
internal objects called “fibers” to hold additional information about the component tree. They may
also be considered a part of “virtual DOM” implementation in React.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
This function is a valid React component because it accepts a single “props” (which stands for
properties) object argument with data and returns a React element. We call such components
“function components” because they are literally JavaScript functions.
Function and Class components both have some additional features that we will discuss in the
next sections.
Rendering a Component
Previously, we only encountered React elements that represent DOM tags:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
const element = <Welcome name="Sara" />;
root.render(element);
Try it on CodePen
React treats components starting with lowercase letters as DOM tags. For example, <div />
represents an HTML div tag, but <Welcome /> represents a component and requires Welcome to
be in scope.
Composing Components
Components can refer to other components in their output. This lets us use the same component
abstraction for any level of detail. A button, a form, a dialog, a screen: in React apps, all those are
commonly expressed as components.
For example, we can create an App component that renders Welcome many times:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
Try it on CodePen
Typically, new React apps have a single App component at the very top. However, if you integrate
React into an existing app, you might start bottom-up with a small component like Button and
gradually work your way to the top of the view hierarchy.
React Components
Components are independent and reusable bits of code. They serve the same purpose as
JavaScript functions, but work in isolation and return HTML.
Components come in two types, Class components and Function components, in this tutorial we
will concentrate on Function components.
In older React code bases, you may find Class components primarily used. It is now suggested to
use Function components along with Hooks, which were added in React 16.8. There is an optional
section on Class components for your reference.
Class Component
A class component must include the extends React.Component statement. This statement creates
an inheritance to React.Component, and gives your component access to React.Component's
functions.
The component also requires a render() method, this method returns HTML.
Example
Create a Class component called Car
Function Component
Here is the same example as above, but created using a Function component instead.
A Function component also returns HTML, and behaves much the same way as a Class component,
but Function components can be written using much less code, are easier to understand, and will
be preferred in this tutorial.
Example
Create a Function component called Car
function Car() {
return <h2>Hi, I am a Car!</h2>;
}
Rendering a Component
Now your React application has a component called Car, which returns an <h2> element.
To use this component in your application, use similar syntax as normal HTML: <Car />
Example
Display the Car component in the "root" element:
Props
Components can be passed as props, which stands for properties.
Props are like function arguments, and you send them into the component as attributes.
Example
Use an attribute to pass a color to the Car component, and use it in the render() function:
function Car(props) {
return <h2>I am a {props.color} Car!</h2>;
}
Components in Components
We can refer to components inside other components:
Example
Use the Car component inside the Garage component:
function Car() {
return <h2>I am a Car!</h2>;
}
function Garage() {
return (
<>
<h1>Who lives in my Garage?</h1>
<Car />
</>
);
}
Components in Files
React is all about re-using code, and it is recommended to split your components into separate
files.
To do that, create a new file with a .js file extension and put the code inside it:
Example
This is the new file, we named it "Car.js":
function Car() {
return <h2>Hi, I am a Car!</h2>;
}
To be able to use the Car component, you have to import the file in your application.
Example
Now we import the "Car.js" file in the application, and we can use the Car component as if it was
created here.
function
(props) {
return <h2>Hi, I'm {props.name}</h2>;
}
Your First Component
Components are one of the core concepts of React. They are the foundation upon which you build
user interfaces (UI), which makes them the perfect place to start your React journey!
On the Web, HTML lets us create rich structured documents with its built-in set of tags like <h1>
and <li>:
<article>
<h1>My First Component</h1>
<ol>
<li>Components: UI Building Blocks</li>
<li>Defining a Component</li>
<li>Using a Component</li>
</ol>
</article>
This markup represents this article <article>, its heading <h1>, and an (abbreviated) table of
contents as an ordered list <ol>. Markup like this, combined with CSS for style, and JavaScript for
interactivity, lies behind every sidebar, avatar, modal, dropdown—every piece of UI you see on
the Web.
React lets you combine your markup, CSS, and JavaScript into custom “components”, reusable UI
elements for your app. The table of contents code you saw above could be turned into a
<TableOfContents /> component you could render on every page. Under the hood, it still uses
the same HTML tags like <article>, <h1>, etc.
Just like with HTML tags, you can compose, order and nest components to design whole pages.
For example, the documentation page you’re reading is made out of React components:
<PageLayout>
<NavigationHeader>
<SearchBar />
<Link to="/docs">Docs</Link>
</NavigationHeader>
<Sidebar />
<PageContent>
<TableOfContents />
<DocumentationText />
</PageContent>
</PageLayout>
As your project grows, you will notice that many of your designs can be composed by reusing
components you already wrote, speeding up your development. Our table of contents above
could be added to any screen with <TableOfContents />! You can even jumpstart your project
with the thousands of components shared by the React open source community like Chakra UI
and Material UI.
Defining a component
Traditionally when creating web pages, web developers marked up their content and then added
interaction by sprinkling on some JavaScript. This worked great when interaction was a nice-to-
have on the web. Now it is expected for many sites and all apps. React puts interactivity first while
still using the same technology: a React component is a JavaScript function that you can sprinkle
with markup. Here’s what that looks like (you can edit the example below):
React components are regular JavaScript functions, but their names must start with a capital letter
or they won’t work!
state = {
name: "World"
};
updateName() {
render() {
return(
<div>
{this.state.name}
</div>
A state can be modified based on user action or network changes Every time the state of an object
changes, React re-renders the component to the browser The state object is initialized in the
constructor The state object can store multiple properties this.setState() is used to change the
value of the state object setState() function performs a shallow merge between the new and the
previous state. The setState() Method State can be updated in response to event handlers, server
responses, or prop changes. This is done using the setState() method. The setState() method
enqueues all of the updates made to the component state and instructs React to re-render the
component and its children with the updated state.
Always use the setState() method to change the state object, since it will ensure that the
component knows it’s been updated and calls the render() method.
constructor(props) {
super(props);
this.state = {
make: "Yamaha",
model: "R15",
color: "blue"
};
changeBikeColor = () => {
this.setState({color: "black"});
render() {
return (
<div>
<h2>My {this.state.make}</h2>
<p>
It is a {this.state.color}
{this.state.model}.
</p>
<button
type="button"
onClick={this.changeBikeColor}
>Change color</button>
</div>
);
n ReactJS, the props are a type of object where the value of attributes of a tag is stored. The word
“props” implies “properties”, and its working functionality is quite similar to HTML attributes.
Basically, these props components are read-only components. In ReactJS, the data can be passed
from one component to another component using these props, similar to how the arguments are
passed in a function. Inside the component, we can add the attributes called props; however, we
cannot change or modify props inside the component as they are immutable.
The code below is the Main.js file. Here, we pass the dynamic data for name attribute within the
App component through the render method called reactDOM.render.
The below code is for App.js. Here, we are using the dynamic data for the name attribute which
the Main.js file has passed as props, and making the props available within this App component
using “this.props”.
render() {
return (
<div>
<p> <h4> Here you will get to know so many things and your knowledge will be enhanced
. </h4> </p>
</div>
);
Example:
Here in the code below, we can see how the default props are set within App.js.
render() {
return (
<div>
<p>Here you will get to know so many things and your knowledge will be enhanced .</p>
</div>
);
App.defaultProps = {
As shown in the code below, default props do not need to be passed through the render method
called reactDOM.render() within the Main.js file of the ReactJS project.
ReactDOM.render(<App/>, document.getElementById('app'));
We can combine both the state and props within our application in ReactJS. The steps for this
combination process of the states and props within our ReactJS are as follows:
Example:
The code given below is for the App.js file. This code shows how we can set the state in our parent
component and then pass it within the child component as the props and use it.
constructor(props) {
super(props);
this.state = {
render() {
return (
<div>
</div>
);
}
}
React components are composed in a hierarchy that mimics the DOM tree hierarchy that they are
used to create. There are those components that are higher (parents) and those components that
are lower (children) in the hierarchy. Let's take a look at the directional communication and data
flow that React enables between components.
If a parent component wants to feed data to a child component, it simply passes it via props. Let's
say that we have a BookList component that contains data for a list of books. As it iterates through
the book list at render time, it wants to pass the details of each book in its list to the child Book
component. It can do that through props. These props are passed to the child component as
attributes in JSX:
function BookList() {
const list = [
{ title: 'A Christmas Carol', author: 'Charles Dickens' },
{ title: 'The Mansion', author: 'Henry Van Dyke' },
// ...
]
return (
<ul>
{list.map((book, i) => <Book title={book.title} author={book.author} key={i} />)}
</ul>
)
}
js
Then the Book component can receive and use those fields as contained in the props parameter
to its function:
function Book(props) {
return (
<li>
<h2>{props.title</h2>
<div>{props.author}</div>
</li>
)
}
js
Favor this simplest form of data passing whenever it makes sense.
There is a limitation here, however, because props are immutable. Data that is passed in props
should never be changed. But then how does a child communicate back to its parent component?
One answer is callbacks.
function BookTitle(props) {
return (
<label>
Title:
<input onChange={props.onTitleChange} value={props.title} />
</label>
)
}
js
It receives a onTitleChange function in the props, sent from its parent. It binds this function to the
onChange event on the <input /> field. When the input changes, it will call the onTitleChange
callback, passing the change Event object.
Because the parent, BookEditForm, has reference to this function, it can receive the arguments
that are passed to the function:
function BookEditForm(props) {
const [title, setTitle] = useState(props.book.title)
function handleTitleChange(evt) {
setTitle(evt.target.value)
}
return (
<form>
<BookTitle onTitleChange={handleTitleChange} title={title} />
</form>
)
}
js
In this case, the parent passed handleTitleChange, and when it's called, it sets the internal state
based on the value of evt.target.value -- a value that has come as a callback argument from the
child component.
There are some cases, however, when data sent through props might not be the best option for
communicating between components. For these cases, React provides a mechanism called
context.
Lifecycle of Components
Each component in React has a lifecycle which you can monitor and manipulate during its
three main phases.
Mounting
Mounting means putting elements into the DOM. React has four built-in methods that gets called,
in this order, when mounting a component:
constructor()
getDerivedStateFromProps()
render()
componentDidMount()
The render() method is required and will always be called, the others are optional and will be
called if you define them.
constructor
The constructor() method is called before anything else, when the component is initiated, and it
is the natural place to set up the initial state and other initial values.
The constructor() method is called with the props, as arguments, and you should always start by
calling the super(props) before anything else, this will initiate the parent's constructor method and
allows the component to inherit methods from its parent (React.Component).
Example:
The constructor method is called, by React, every time you make a component:
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
render() {
return (
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
);
}
}
This is the natural place to set the state object based on the initial props.
It takes state as an argument, and returns an object with changes to the state.
The example below starts with the favorite color being "red", but the getDerivedStateFromProps()
method updates the favorite color based on the favcol attribute:
Example:
The getDerivedStateFromProps method is called right before the render method:
Example:
A simple component with a simple render() method:
componentDidMount
The componentDidMount() method is called after the component is rendered.
This is where you run statements that requires that the component is already placed in the DOM.
Example:
At first my favorite color is red, but give me a second, and it is yellow instead:
React has five built-in methods that gets called, in this order, when a component is updated:
getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
The render() method is required and will always be called, the others are optional and will be
called if you define them.
getDerivedStateFromProps
Also at updates the getDerivedStateFromProps method is called. This is the first method that is
called when a component gets updated.
This is still the natural place to set the state object based on the initial props.
The example below has a button that changes the favorite color to blue, but since the
getDerivedStateFromProps() method is called, which updates the state with the color from the
favcol attribute, the favorite color is still rendered as yellow:
Example:
If the component gets updated, the getDerivedStateFromProps() method is called:
shouldComponentUpdate
In the shouldComponentUpdate() method you can return a Boolean value that specifies whether
React should continue with the rendering or not.
The example below shows what happens when the shouldComponentUpdate() method returns
false:
Example:
Stop the component from rendering at any update:
Example:
Same example as above, but this time the shouldComponentUpdate() method returns true
instead:
render
The render() method is of course called when a component gets updated, it has to re-render the
HTML to the DOM, with the new changes.
The example below has a button that changes the favorite color to blue:
Example:
Click the button to make a change in the component's state:
getSnapshotBeforeUpdate
In the getSnapshotBeforeUpdate() method you have access to the props and state before the
update, meaning that even after the update, you can check what the values were before the
update.
The example below might seem complicated, but all it does is this:
When the component is mounting it is rendered with the favorite color "red".
When the component has been mounted, a timer changes the state, and after one second, the
favorite color becomes "yellow".
This action triggers the update phase, and since this component has a getSnapshotBeforeUpdate()
method, this method is executed, and writes a message to the empty DIV1 element.
Then the componentDidUpdate() method is executed and writes a message in the empty DIV2
element:
Example:
Use the getSnapshotBeforeUpdate() method to find out what the state object looked like before
the update:
componentDidUpdate
The componentDidUpdate method is called after the component is updated in the DOM.
The example below might seem complicated, but all it does is this:
When the component is mounting it is rendered with the favorite color "red".
When the component has been mounted, a timer changes the state, and the color becomes
"yellow".
This action triggers the update phase, and since this component has a componentDidUpdate
method, this method is executed and writes a message in the empty DIV element:
Example:
The componentDidUpdate method is called after the update has been rendered in the DOM:
Unmounting
The next phase in the lifecycle is when a component is removed from the DOM, or unmounting
as React likes to call it.
React has only one built-in method that gets called when a component is unmounted:
componentWillUnmount()
componentWillUnmount
The componentWillUnmount method is called when the component is about to be removed from
the DOM.
Example:
Click the button to delete the header:
Error Handling
There are two main methods in error handling. These method are used in the error boundary
mechanism in React. We wrap the component ( from where there is a possibility of error
occurrences ) in a class which handles the below methods.
componentDidCatch(error, info): we can log the errors using api call. This is helpful in displaying
useful error message on screen instead of technical errors.
A class can be termed as an error boundary if it implements at least one method from above two
error handling lifecycle methods. Its main purpose is to show a fallback ui once we get an error.
If error is not cached by error boundary class then the entire react component tree below that
component will be removed.
We can use the try catch in some methods but in application wide using error boundary is better
standard. It keeps the declarative nature of react intact.
Please note − Error boundary feature works in production mode. In development mode it will
display the actual errors directly on browser.
Week5_Day3_Session2
What is JSX?
JSX, or JavaScript XML, is a syntax extension for JavaScript used in React to describe the UI. It
looks similar to HTML but can include JavaScript expressions and is compiled to JavaScript at
runtime. JSX makes it easier to write and understand the structure of the UI components,
allowing developers to intersperse HTML-like syntax with JavaScript logic.
jsx
Copy code
const element = <h1>Hello, world!</h1>;
jsx
Copy code
const name = 'John';
const element = <h1>Hello, {name}!</h1>;
jsx
Copy code
const element = <img src="logo.png" alt="Logo" />;
jsx
Copy code
const element = (
<div>
<h1>Hello, world!</h1>
<p>Welcome to my website.</p>
</div>
);
jsx
Copy code
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
1. Using Jest and React Testing Library: Jest is a testing framework often used with React,
and React Testing Library provides utilities to test React components.
2. Setting Up: Ensure you have Jest and React Testing Library installed:
sh
Copy code
npm install --save-dev jest @testing-library/react @testing-library/jest-dom
3. Writing a Test: Create a test file, typically with the .test.js or .spec.js extension.
jsx
Copy code
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import Welcome from './Welcome';
4. Running Tests: You can run your tests using the jest command or with an npm script.
sh
Copy code
npm test
5. Testing User Interactions: React Testing Library allows simulating user interactions.
jsx
Copy code
import React from 'react';
import { render, fireEvent, screen } from '@testing-library/react';
import Counter from './Counter';
Summary
• JSX: A syntax extension for JavaScript, resembling HTML, used in React to describe UI.
• Creating JSX Elements: Use HTML-like syntax in JavaScript to define UI elements, with
support for embedding expressions, setting attributes, and nesting elements.
• Testing Components: Use Jest and React Testing Library to write and run tests, ensuring
components render correctly and handle user interactions as expected.
Week5_Day4_Session1
Handling Events
Handling events with React elements is very similar to handling events on DOM elements.
There are some syntax differences:
<button onclick="activateLasers()">
Activate Lasers
</button>
is slightly different in React:
<button onClick={activateLasers}>
Activate Lasers
</button>
Another difference is that you cannot return false to prevent default behavior in React. You must
call preventDefault explicitly. For example, with plain HTML, to prevent the default form behavior
of submitting, you can write:
function Form() {
function handleSubmit(e) {
e.preventDefault();
console.log('You clicked submit.');
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}
Here, e is a synthetic event. React defines these synthetic events according to the W3C spec, so
you don’t need to worry about cross-browser compatibility. React events do not work exactly the
same as native events. See the SyntheticEvent reference guide to learn more.
When using React, you generally don’t need to call addEventListener to add listeners to a DOM
element after it is created. Instead, just provide a listener when the element is initially rendered.
When you define a component using an ES6 class, a common pattern is for an event handler to
be a method on the class. For example, this Toggle component renders a button that lets the user
toggle between “ON” and “OFF” states:
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
Try it on CodePen
You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are
not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be
undefined when the function is actually called.
This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you
refer to a method without () after it, such as onClick={this.handleClick}, you should bind that
method.
If calling bind annoys you, there are two ways you can get around this. You can use public class
fields syntax to correctly bind callbacks:
If you aren’t using class fields syntax, you can use an arrow function in the callback:
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}
The problem with this syntax is that a different callback is created each time the LoggingButton
renders. In most cases, this is fine. However, if this callback is passed as a prop to lower
components, those components might do an extra re-rendering. We generally recommend
binding in the constructor or using the class fields syntax, to avoid this sort of performance
problem.
Conditional Rendering
In React, you can create distinct components that encapsulate behavior you need. Then,
you can render only some of them, depending on the state of your application.
Conditional rendering in React works the same way conditions work in JavaScript. Use JavaScript
operators like if or the conditional operator to create elements representing the current state, and
let React update the UI to match them.
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
We’ll create a Greeting component that displays either of these components depending on
whether a user is logged in:
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
This example renders a different greeting depending on the value of isLoggedIn prop.
Element Variables
You can use variables to store elements. This can help you conditionally render a part of the
component while the rest of the output doesn’t change.
Consider these two new components representing Logout and Login buttons:
function LoginButton(props) {
return (
<button onClick={props.onClick}>
Login
</button>
);
}
function LogoutButton(props) {
return (
<button onClick={props.onClick}>
Logout
</button>
);
}
In the example below, we will create a stateful component called LoginControl.
It will render either <LoginButton /> or <LogoutButton /> depending on its current state. It will
also render a <Greeting /> from the previous example:
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
While declaring a variable and using an if statement is a fine way to conditionally render a
component, sometimes you might want to use a shorter syntax. There are a few ways to inline
conditions in JSX, explained below.
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
);
}
Therefore, if the condition is true, the element right after && will appear in the output. If it is false,
React will ignore and skip it.
Note that returning a falsy expression will still cause the element after && to be skipped but will
return the falsy expression. In the example below, <div>0</div> will be returned by the render
method.
render() {
const count = 0;
return (
<div>
{count && <h1>Messages: {count}</h1>}
</div>
);
}
Inline If-Else with Conditional Operator
Another method for conditionally rendering elements inline is to use the JavaScript conditional
operator condition ? true : false.
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
</div>
);
}
It can also be used for larger expressions although it is less obvious what’s going on:
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn
? <LogoutButton onClick={this.handleLogoutClick} />
: <LoginButton onClick={this.handleLoginClick} />
}
</div>
);
}
Just like in JavaScript, it is up to you to choose an appropriate style based on what you and your
team consider more readable. Also remember that whenever conditions become too complex, it
might be a good time to extract a component.
In the example below, the <WarningBanner /> is rendered depending on the value of the prop
called warn. If the value of the prop is false, then the component does not render:
function WarningBanner(props) {
if (!props.warn) {
return null;
}
return (
<div className="warning">
Warning!
</div>
);
}
handleToggleClick() {
this.setState(state => ({
showWarning: !state.showWarning
}));
}
render() {
return (
<div>
<WarningBanner warn={this.state.showWarning} />
<button onClick={this.handleToggleClick}>
{this.state.showWarning ? 'Hide' : 'Show'}
</button>
</div>
);
}
}
Returning null from a component’s render method does not affect the firing of the component’s
lifecycle methods. For instance componentDidUpdate will still be called.
Given the code below, we use the map() function to take an array of numbers and double their
values. We assign the new array returned by map() to the variable doubled and log it:
Below, we loop through the numbers array using the JavaScript map() function. We return a <li>
element for each item. Finally, we assign the resulting array of elements to listItems:
<ul>{listItems}</ul>
Try it on CodePen
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li>{number}</li>
);
return (
<ul>{listItems}</ul>
);
}
Let’s assign a key to our list items inside numbers.map() and fix the missing key issue.
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
Try it on CodePen
Keys
Keys help React identify which items have changed, are added, or are removed. Keys should be
given to the elements inside the array to give the elements a stable identity:
Here is an in-depth explanation about why keys are necessary if you’re interested in learning more.
For example, if you extract a ListItem component, you should keep the key on the <ListItem />
elements in the array rather than on the <li> element in the ListItem itself.
function ListItem(props) {
const value = props.value;
return (
// Wrong! There is no need to specify the key here:
<li key={value.toString()}>
{value}
</li>
);
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Wrong! The key should have been specified here:
<ListItem value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
Example: Correct Key Usage
function ListItem(props) {
// Correct! There is no need to specify the key here:
return <li>{props.value}</li>;
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Correct! Key should be specified inside the array.
<ListItem key={number.toString()} value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
Try it on CodePen
A good rule of thumb is that elements inside the map() call need keys.
function Blog(props) {
const sidebar = (
<ul>
{props.posts.map((post) =>
<li key={post.id}>
{post.title}
</li>
)}
</ul>
);
const content = props.posts.map((post) =>
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.content}</p>
</div>
);
return (
<div>
{sidebar}
<hr />
{content}
</div>
);
}
const posts = [
{id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
{id: 2, title: 'Installation', content: 'You can install React from npm.'}
];
Keys serve as a hint to React but they don’t get passed to your components. If you need the same
value in your component, pass it explicitly as a prop with a different name:
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
JSX allows embedding any expression in curly braces so we could inline the map() result:
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
)}
</ul>
);
}
Try it on CodePen
Sometimes this results in clearer code, but this style can also be abused. Like in JavaScript, it is up
to you to decide whether it is worth extracting a variable for readability. Keep in mind that if the
map() body is too nested, it might be a good time to extract a component.
HTML form elements work a bit differently from other DOM elements in React, because form
elements naturally keep some internal state. For example, this form in plain HTML accepts a single
name:
<form>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>
This form has the default HTML form behavior of browsing to a new page when the user submits
the form. If you want this behavior in React, it just works. But in most cases, it’s convenient to have
a JavaScript function that handles the submission of the form and has access to the data that the
user entered into the form. The standard way to achieve this is with a technique called “controlled
components”.
Week5_Day4_Session2
Controlled Components
In HTML, form elements such as <input>, <textarea>, and <select> typically maintain their
own state and update it based on user input. In React, mutable state is typically kept in the state
property of components, and only updated with setState().
We can combine the two by making the React state be the “single source of truth”. Then the React
component that renders a form also controls what happens in that form on subsequent user input.
An input form element whose value is controlled by React in this way is called a “controlled
component”.
For example, if we want to make the previous example log the name when it is submitted, we can
write the form as a controlled component:
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
Try it on CodePen
Since the value attribute is set on our form element, the displayed value will always be
this.state.value, making the React state the source of truth. Since handleChange runs on every
keystroke to update the React state, the displayed value will update as the user types.
With a controlled component, the input’s value is always driven by the React state. While this
means you have to type a bit more code, you can now pass the value to other UI elements too, or
reset it from other event handlers.
<textarea>
Hello there, this is some text in a text area
</textarea>
In React, a <textarea> uses a value attribute instead. This way, a form using a <textarea> can be
written very similarly to a form that uses a single-line input:
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('An essay was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Essay:
<textarea value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
Notice that this.state.value is initialized in the constructor, so that the text area starts off with some
text in it.
<select>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option selected value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
Note that the Coconut option is initially selected, because of the selected attribute. React, instead
of using this selected attribute, uses a value attribute on the root select tag. This is more
convenient in a controlled component because you only need to update it in one place. For
example:
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('Your favorite flavor is: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Pick your favorite flavor:
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
Try it on CodePen
Overall, this makes it so that <input type="text">, <textarea>, and <select> all work very similarly
- they all accept a value attribute that you can use to implement a controlled component.
Note
You can pass an array into the value attribute, allowing you to select multiple options in a select
tag:
For example:
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}
Try it on CodePen
Note how we used the ES6 computed property name syntax to update the state key
corresponding to the given input name:
this.setState({
[name]: value
});
It is equivalent to this ES5 code:
The following code demonstrates this. (The input is locked at first but becomes editable after a
short delay.)
setTimeout(function() {
ReactDOM.createRoot(mountNode).render(<input value={null} />);
}, 1000);
Uncontrolled Components
It can sometimes be tedious to use controlled components, because you need to write an event
handler for every way your data can change and pipe all of the input state through a React
component. This can become particularly annoying when you are converting a preexisting
codebase to React, or integrating a React application with a non-React library. In these situations,
you might want to check out uncontrolled components, an alternative technique for
implementing input forms.
Fully-Fledged Solutions
If you’re looking for a complete solution including validation, keeping track of the visited fields,
and handling form submission, Formik is one of the popular choices. However, it is built on the
same principles of controlled components and managing state — so don’t neglect to learn them.
Uncontrolled Components
In most cases, we recommend using controlled components to implement forms. In a controlled
component, form data is handled by a React component. The alternative is uncontrolled
components, where form data is handled by the DOM itself.
To write an uncontrolled component, instead of writing an event handler for every state update,
you can use a ref to get form values from the DOM.
handleSubmit(event) {
alert('A name was submitted: ' + this.input.current.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" ref={this.input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
Try it on CodePen
Since an uncontrolled component keeps the source of truth in the DOM, it is sometimes easier to
integrate React and non-React code when using uncontrolled components. It can also be slightly
less code if you want to be quick and dirty. Otherwise, you should usually use controlled
components.
If it’s still not clear which type of component you should use for a particular situation, you might
find this article on controlled versus uncontrolled inputs to be helpful.
Default Values
In the React rendering lifecycle, the value attribute on form elements will override the value in the
DOM. With an uncontrolled component, you often want React to specify the initial value, but leave
subsequent updates uncontrolled. To handle this case, you can specify a defaultValue attribute
instead of value. Changing the value of defaultValue attribute after a component has mounted
will not cause any update of the value in the DOM.
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input
defaultValue="Bob"
type="text"
ref={this.input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
Likewise, <input type="checkbox"> and <input type="radio"> support defaultChecked, and
<select> and <textarea> supports defaultValue.
You should use the File API to interact with the files. The following example shows how to create
a ref to the DOM node to access file(s) in a submit handler:
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Upload file:
<input type="file" ref={this.fileInput} />
</label>
<br />
<button type="submit">Submit</button>
</form>
);
}
}
Lifting State Up
Often, several components need to reflect the same changing data. We recommend lifting the
shared state up to their closest common ancestor. Let’s see how this works in action.
In this section, we will create a temperature calculator that calculates whether the water would
boil at a given temperature.
We will start with a component called BoilingVerdict. It accepts the celsius temperature as a prop,
and prints whether it is enough to boil the water:
function BoilingVerdict(props) {
if (props.celsius >= 100) {
return <p>The water would boil.</p>;
}
return <p>The water would not boil.</p>;
}
Next, we will create a component called Calculator. It renders an <input> that lets you enter the
temperature, and keeps its value in this.state.temperature.
handleChange(e) {
this.setState({temperature: e.target.value});
}
render() {
const temperature = this.state.temperature;
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input
value={temperature}
onChange={this.handleChange} />
<BoilingVerdict
celsius={parseFloat(temperature)} />
</fieldset>
);
}
}
Try it on CodePen
We can start by extracting a TemperatureInput component from Calculator. We will add a new
scale prop to it that can either be "c" or "f":
const scaleNames = {
c: 'Celsius',
f: 'Fahrenheit'
};
handleChange(e) {
this.setState({temperature: e.target.value});
}
render() {
const temperature = this.state.temperature;
const scale = this.props.scale;
return (
<fieldset>
<legend>Enter temperature in {scaleNames[scale]}:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
We can now change the Calculator to render two separate temperature inputs:
We have two inputs now, but when you enter the temperature in one of them, the other doesn’t
update. This contradicts our requirement: we want to keep them in sync.
We also can’t display the BoilingVerdict from Calculator. The Calculator doesn’t know the current
temperature because it is hidden inside the TemperatureInput.
function toCelsius(fahrenheit) {
return (fahrenheit - 32) * 5 / 9;
}
function toFahrenheit(celsius) {
return (celsius * 9 / 5) + 32;
}
These two functions convert numbers. We will write another function that takes a string
temperature and a converter function as arguments and returns a string. We will use it to calculate
the value of one input based on the other input.
It returns an empty string on an invalid temperature, and it keeps the output rounded to the third
decimal place:
Lifting State Up
Currently, both TemperatureInput components independently keep their values in the local state:
handleChange(e) {
this.setState({temperature: e.target.value});
}
render() {
const temperature = this.state.temperature;
// ...
However, we want these two inputs to be in sync with each other. When we update the Celsius
input, the Fahrenheit input should reflect the converted temperature, and vice versa.
In React, sharing state is accomplished by moving it up to the closest common ancestor of the
components that need it. This is called “lifting state up”. We will remove the local state from the
TemperatureInput and move it into the Calculator instead.
If the Calculator owns the shared state, it becomes the “source of truth” for the current
temperature in both inputs. It can instruct them both to have values that are consistent with each
other. Since the props of both TemperatureInput components are coming from the same parent
Calculator component, the two inputs will always be in sync.
render() {
// Before: const temperature = this.state.temperature;
const temperature = this.props.temperature;
// ...
We know that props are read-only. When the temperature was in the local state, the
TemperatureInput could just call this.setState() to change it. However, now that the temperature
is coming from the parent as a prop, the TemperatureInput has no control over it.
In React, this is usually solved by making a component “controlled”. Just like the DOM <input>
accepts both a value and an onChange prop, so can the custom TemperatureInput accept both
temperature and onTemperatureChange props from its parent Calculator.
handleChange(e) {
// Before: this.setState({temperature: e.target.value});
this.props.onTemperatureChange(e.target.value);
// ...
Note:
The onTemperatureChange prop will be provided together with the temperature prop by the
parent Calculator component. It will handle the change by modifying its own local state, thus re-
rendering both inputs with the new values. We will look at the new Calculator implementation
very soon.
Before diving into the changes in the Calculator, let’s recap our changes to the TemperatureInput
component. We have removed the local state from it, and instead of reading
this.state.temperature, we now read this.props.temperature. Instead of calling this.setState() when
we want to make a change, we now call this.props.onTemperatureChange(), which will be provided
by the Calculator:
handleChange(e) {
this.props.onTemperatureChange(e.target.value);
}
render() {
const temperature = this.props.temperature;
const scale = this.props.scale;
return (
<fieldset>
<legend>Enter temperature in {scaleNames[scale]}:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
Now let’s turn to the Calculator component.
We will store the current input’s temperature and scale in its local state. This is the state we “lifted
up” from the inputs, and it will serve as the “source of truth” for both of them. It is the minimal
representation of all the data we need to know in order to render both inputs.
For example, if we enter 37 into the Celsius input, the state of the Calculator component will be:
{
temperature: '37',
scale: 'c'
}
If we later edit the Fahrenheit field to be 212, the state of the Calculator will be:
{
temperature: '212',
scale: 'f'
}
We could have stored the value of both inputs but it turns out to be unnecessary. It is enough to
store the value of the most recently changed input, and the scale that it represents. We can then
infer the value of the other input based on the current temperature and scale alone.
The inputs stay in sync because their values are computed from the same state:
handleCelsiusChange(temperature) {
this.setState({scale: 'c', temperature});
}
handleFahrenheitChange(temperature) {
this.setState({scale: 'f', temperature});
}
render() {
const scale = this.state.scale;
const temperature = this.state.temperature;
const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;
return (
<div>
<TemperatureInput
scale="c"
temperature={celsius}
onTemperatureChange={this.handleCelsiusChange} />
<TemperatureInput
scale="f"
temperature={fahrenheit}
onTemperatureChange={this.handleFahrenheitChange} />
<BoilingVerdict
celsius={parseFloat(celsius)} />
</div>
);
}
}
Try it on CodePen
Now, no matter which input you edit, this.state.temperature and this.state.scale in the Calculator
get updated. One of the inputs gets the value as is, so any user input is preserved, and the other
input value is always recalculated based on it.
React calls the function specified as onChange on the DOM <input>. In our case, this is the
handleChange method in the TemperatureInput component.
The handleChange method in the TemperatureInput component calls
this.props.onTemperatureChange() with the new desired value. Its props, including
onTemperatureChange, were provided by its parent component, the Calculator.
When it previously rendered, the Calculator had specified that onTemperatureChange of the
Celsius TemperatureInput is the Calculator’s handleCelsiusChange method, and
onTemperatureChange of the Fahrenheit TemperatureInput is the Calculator’s
handleFahrenheitChange method. So either of these two Calculator methods gets called
depending on which input we edited.
Inside these methods, the Calculator component asks React to re-render itself by calling
this.setState() with the new input value and the current scale of the input we just edited.
React calls the Calculator component’s render method to learn what the UI should look like. The
values of both inputs are recomputed based on the current temperature and the active scale. The
temperature conversion is performed here.
React calls the render methods of the individual TemperatureInput components with their new
props specified by the Calculator. It learns what their UI should look like.
React calls the render method of the BoilingVerdict component, passing the temperature in Celsius
as its props.
React DOM updates the DOM with the boiling verdict and to match the desired input values. The
input we just edited receives its current value, and the other input is updated to the temperature
after conversion.
Every update goes through the same steps so the inputs stay in sync.
Lessons Learned
There should be a single “source of truth” for any data that changes in a React application. Usually,
the state is first added to the component that needs it for rendering. Then, if other components
also need it, you can lift it up to their closest common ancestor. Instead of trying to sync the state
between different components, you should rely on the top-down data flow.
Lifting state involves writing more “boilerplate” code than two-way binding approaches, but as a
benefit, it takes less work to find and isolate bugs. Since any state “lives” in some component and
that component alone can change it, the surface area for bugs is greatly reduced. Additionally,
you can implement any custom logic to reject or transform user input.
If something can be derived from either props or state, it probably shouldn’t be in the state. For
example, instead of storing both celsiusValue and fahrenheitValue, we store just the last edited
temperature and its scale. The value of the other input can always be calculated from them in the
render() method. This lets us clear or apply rounding to the other field without losing any precision
in the user input.
Assignments Questions
1. List and explain JS objects.
2. What is this? Explain with an example.
3. Explain JS objects methods. How do you access it, explain with an example.
4. Explain with an example JS objects constructors.
5. Explain with example how do you
▪ Access JavaScript Properties
▪ Add JavaScript Properties
6. Discuss with an example accessor properties in JS
7. Explain with an example JavaScript Object Prototypes
8. Write a note on E6 arrow functions advantages with an example.
9. Explain in brief JavaScript strings
10. Write a note with example on to add properties and methods in following objects
▪ Number, Boolean, String and Date
11. What is the use of Spread Operator? Explain with example
12. Discuss the various Map object’s methods with example
13. Discuss the Weak Maps with example, how they differ with normal Maps
14. Discuss the various set object’s methods with example
15. Create a single-page applications. React allows us to create reusable UI components.
16. Explain with an example JSX expression.
17. Why JSX? Explain
18. Explain with example how to render an element in the DOM
19. Explain with example how to update the rendered element
20. Explain with example react-dom package
21. What is the Virtual DOM? explain
22. Write a JavaScript function to define a component.
23. What do you mean by composing components? Explain
24. What is component in react? Explain its types with an example.
25. What Is ‘State’ in ReactJS ? Explain with example
26. Discuss communication between components using props.
27. List and explain components in React has a lifecycle which are monitored and manipulated
during its three main phases.
28. Discuss two main methods in error handling
29. Explain with example conditional rendering
30. Explain lists and keys with example