0% found this document useful (0 votes)
22 views18 pages

Chapter 08

Uploaded by

HARSH VAIDYA
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views18 pages

Chapter 08

Uploaded by

HARSH VAIDYA
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

Important Points :-

• Video on Critical Rendering Path :- https://www.youtube.com/watch?v=PkOBnYxqj3k


• Code for shimmer effect loading for cards :- https://codepen.io/andru255/pen/wvBdxbb
• Article for data binding in React :- https://www.joshwcomeau.com/react/data-binding/
• Best way for understanding Formik :- https://formik.org/docs/tutorial#the-basics

Nested Paths :-
A path inside another path. It can be created by making a children array for an already existing children. Ex :-

In the 1st layer of children, we are specifying path with the suffix “/”,
which denotes root (like -> “/about”). We could have also written
“about” instead and it would work just fine because the parent path is
already specified as root (since it’s written path: “/” ).

However, in the nested path, always write just the name in the path
argument (like :- path: ”profile”), and not path: “/profile”. This is because
in the latter one, the actual path will be treated as
“localhost:1234/profile”, since as stated earlier, “/” denotes root path.
However, in the former case, the actual path will be
“localhost:1234/about/profile”.

But, this syntax will just show the About component only and not the
Profile component.

This is because, children are always rendered within an Outlet component and Outlet should be created inside the parent.
This was done just for the sake of showing an example. We actually want our profile component to be always present in our
About component, so we will just import our Profile component and use it instead of the Outlet.

Class Based Components :-


When react was launched, class based components was the norm. Just like a functional component, a class component is also
very similar to a normal JS class, but it extends the Component class of React to denote that it’s not a normal JS class. Let’s
create a component named “ProfileClass”.
You cannot create a class-based component without a render() method. Just like a functional component, returns a JSX using
a keyword return, a class-based component (CBC) returns JSX using the render(). In the below image, try to compare a class
component with a functional one :-

Passing props :- Here, we pass props using the keyword “this”.


Using state (creating the state variable):-
In functional comp. we used to import the useState hook. We know that classes have a constructor and constructor is a
special member function used for initialisation and hence we create the state variables inside a class constructor. Now, we
use useState to create state variables, but earlier we used this.state object ,given to us by React, just like this.props. In that
object we can write the state variables with their initial value in the form of key-value pairs. Again showing the difference
between FC and CBC.

We can also destructure both the this.props and this.state object :-


Now, to create multiple set variables, in FC,
we used to create them separately, but here
in CBC, we will create them in the same
this.state object like :-

Using state (using the set function):-


We know that if we the set function for updating the value of a set variable, instead of doing normally like ->
“setVar = newValue”,
React will trigger the reconciliation cycle on encountering it and keep our UI in sync with it. Similarly, for CBC, React gives
access to a function called setState, where we pass the modified object as parameter. Never mutate state directly. In the
below example we have shown how to update even 2 state variables in both FC and CBC :-
After clicking both the buttons :-

• Important Point regarding Class Component :-


Every React Class component is called a React Life Cycle. Everytime, we go into a life cycle, firstly the constructor is called and
then the component is rendered.
Everytime I refresh the page and click on the button
“ClassButton” :-

So, the constructor is called only once, but everytime the UI is updated, the render() function is definitely called.

Doing API call in CBC :-


In FC, we used to do API Call in the useEffect() because it got called after the first render, so that at first we can render
whatever we can in the default state and later on we update the state. On updating, the component is rerendered.
So, in CBC too, first of all we have to render and then update. For this purpose, there is a member function called
componentDidMount(), which will be called after my render.
Whenever a CBC is loaded onto a page, it has some Life-Cycle methods that are called. The constructor, render(),
componentDidMount() are those Life-Cycle Methods.
The sequence in which they are called is :-
• First the constructor is called
• Then the component is rendered
• Then the function componentDidMount() is called
The Output is in this order because, in the About component, where the Profile and ProfileClass
components are actually rendered, the Profile component is mentioned first and then the latter,
which is why “render functional” getting printed before “Constructor”.

Converting the About Page from FC to CBC :-


The previous one The CBC one

Also, notice that in the new CBC code, we have imported the Component Class directly from react library.

Output 1 :- An Output to show the flow of how CBC components are called :-
First we render only the ProfileClass component in the About component and remove the Profile component. Then see the
below code and output :-
Output 2 :- Showing how multiple child CBCs are rendered from 1 parent CBC

When React is rendering things up i.e. when reconciliation happens, it does that in 2 phases :-
1. Render phase :- This phase includes the calling of constructor and render().
2. Commit phase :- The phase where React is actually modifying our DOM, and we know that the
componentDidMount() is called after we have updated the DOM (That is why we see the Skimmer effect)

So, the steps involved in the previous example :-


• So, in the above example, first the constructor of About CBC is called, then it’s render().
• React will generate the core HTML that needs to be put in the DOM and we already know that Babel helps us to
convert the given JSX into HTML.
• Now in About page’s JSX, there are 2 child CBC which also needs to be rendered. So, the React also calls the
constructor of 1st child, calls the render() to generate it’s corresponding HTML from the given JSX.
• Now, you might think that after this, the render phase of the first child CBC is over, so commit phase will be done and
then the render phase of the 2nd child CBC will start
• But, the commit phase takes more time than the render phase because in the former, React needs to update the
DOM. That’s why React tells that it should first complete the render phase of all children i.e. it batches up the render
phase of all children
• So, the 2nd child’s render phase starts and it gets completed first
• These are the steps in the Render phase.
• After that the commit phase of 1st and 2nd child gets completed i.e. DOM is updated for children.
• Then React will update the initial parent DOM and then the Parent componentDidMount() gets called
Refer to this diagram (link :- https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/)

**Just pay attention to the Mounting Phase.

Let’s make an API call from componentDidMount():-


We will use a github API to fetch an users called the Users API. Go to this link :-
https://docs.github.com/en/rest/users?apiVersion=2022-11-28 and then click on “Get a user” link :-
The link highlighted with blue is the API link. Just write any name in place of the “USERNAME” and it will give the github data.
Ex :-

To get a response from an API, we are using the fetch() function here, axios can also be implemented. Now, we know that
making an API call requires an async function. If you remember, in our RestaurantMenu.js, where we used useEffect(), we did
not make the callback function async. The reason is written at the bottom of this assignment, as to why we should not write
an async function as a callback in useEffect.
However, we can make the componentDidMount() an async function and fetch API data using fetch()/axios. To store the API
data, we have created another state variable named userInfo.
See the flow of output too :- (Left side is the About.js page i.e the Parent CBC and ProfileClass.js is the child CBC)

Here the “Parent componentDidMount” gets printed and


after that the children’s componentDidMount because
the latter one is inside an async function.

We know that React finishes our Render phase/cycle first and then goes to the commit cycle. That is why all things “Child
render ArpanClassChild 2” is printed first. Then, the componentDidMount() of the parent will get printed first because, that
of the children’s are async and they will take some data to load. Similarly, if we console log the json object too that stores our
response, in the componentDidMount of a child in ProfileClass.js and just render one child component instead of two in
About.js like :-

We will get output in the console like :-

Now, if there are again 2 child CBC in the About.js, which is the parent CBC, with names “ArpanClassChild 1” and
“ArpanClassChild 2”, then below will be the output :-
Now, again we just use the “ArpanClassChild 1” and remove the 2nd one in the About.js, which is the parent CBC. However, if
we write the code of console logging the “Child componentDidMount” before making the API call like below, then we will get
a different output :-

Now, if there are again 2 child CBC in the About.js, which is the parent CBC, with names “ArpanClassChild 1” and
“ArpanClassChild 2”, then below will be the output :-
Remember this diagram :-
Here in the last few examples, when
we are doing this.setState() inside the
child’s componentDidMount(), we are
actually updating the component. So,
looking at the diagram you can say
that, at first the Mounting phase
happens. Here, the constructor is
called, then the render(). This
concludes the render phase of
Mounting. Then commit phase starts
where React updates the DOM with
the default component and
componentDidMount() is called. In our
example, in that function we have made an API call.
So, after the data is fetched from the API, the commit phase of the Mounting is also over.
Now, we actually use that data to update an existing component i.e. rendering the component with the help of setState(). So,
we enter the updating phase of the diagram.
In this, again the render() is called, which concludes the render phase of Updating. Then, the DOM is updated and
componentDidUpdate() is called (if present, in our examples it was not there).

ComponentDidUpdate() Life-Cycle Method :-


As seen from the above diagram, it is called when the rerendering of an existing component and its updation in DOM has
already been done. In simple words, this method will be called after every next render.

ComponentWillUnmount() Life-Cycle Method :-

This method will be called once our component is unmounted i.e. our component is no longer there in the webpage. In our
project it can be seen by writing the below piece of code, which will give the 1st output on entering the URL
“localhost:1234/about” or “localhost:1234/about/profile”. Now, in this page, the About component, along with its child
components (here ProfileClass component) is displayed in the webpage.
The moment we navigate to the Home/Contacts component from the navbar, we will see that the console log inside the
componentWillUnmount() gets printed.
NEVER EVER COMPARE REACT LIFE CYCLE METHODS TO FUNCTIONAL COMPONENT HOOKS
How to mimic the functionality of a dependency array in useEffect(), here in CBC?
The elements of the dependency array in useEffect() used to denote that whenever there is a change in any one those state
variables, the callback function of useEffect() will be called. In CBC, we know that the life-cycle method that gets called after
every update is the componentDidUpdate().
We know that normally, that method is called just after the initial render. So, it is like putting an empty dependency array.
But what if I want it to be called after a state variable is changed?
We pass 2 arguments :- prevProps and prevState.
In the below screenshot on the left side is the CBC named ProfileClass and on the leftside is the FC named Profile. In the FC,
we have a dependency array with 2 state variables :- count and count2. To mimic this functionality, we write that if-else piece
of code in the componentDidUpdate() -> it means that when the state of count or count2 changes, React has to execute the
given statements written inside the if block.

Now, if we wanted to execute 2 different tasks for changes in the state variable count and count2, then in CBC, we have to
write 2 different if blocks and in the FC, we have to write 2 different useEffect()s like :-

Use Case of componentWillUnmount() :-


It is called when a component is unmounted. It means when we move from one component to another component, or rather
one page to another page (not to be confused with React is a single page application. Here we are just using page to mean a
component rather than a webpage). So, when we navigate to another component/page, sometimes we need to clear
something up. For ex :-
Lets we write a setInterval in the componentDidMount() method, which prints a statement “Namaste React OP” after every
sec. Now, when we open the url “localhost:1234/about” in the browser, we will be seeing that statement getting printed
multiple times
Now, when we will navigate to the Home/Contacts page, we would live this setInterval execution to stop. But, that won’t
happen because this is a single page application where only the component is changed by React through it’s reconciliation
process. So, we will still see that statement getting printed in the console.

Now, if we navigate back to the About Page, we will be again calling the componentDidMount() method which has the
setInterval. So, now there will be 2 setIntervals running and if you notice the count of the statement in the console, you will
see that the count is increasing by 2 in every 1 sec.

This is major downside of single page application


So, when we are changing our page, instead of reloading the page, React is changing the components. So, if we again move
to the Contacts/Home page and again navigate back to the About page, the count of that statement getting printed will be 3
in every sec.
To avoid this, we need to cleanup this functionality. We know that when a component unmount, the
componentWillUnmount() will be called and also that to clear a setInterval(), we use a clearInterval(). But, how can we
reference the clearInterval() in the componentWillUnmount() to the setInterval() in the componentDidMount()?
To do that, while writing the setInterval(), store it in a variable using the “this” keyword and reference that variable in the
clearInterval() too like :-
Doing this, the statement will get printed only
when we are in the About page and not any other
page because as soon as we navigate away from
the About Page, that setInterval() will be cleaned
up.

Performing cleanup in the Functional Component :-


Just like in the CBC, if we write a setInterval() in useEffect() of a FC, then it will get executed and never stop. The 1st image is
the code, the 2nd is the output in console when we reload the About page. The 3rd image is when we navigate to the Home
Page and you can see that the statement is still getting printed. Then in the 4th image, it shows the output in console when
we navigate back to the About Page, where you will see that in one second, the statement is getting printed twice just like in
the case of CBC.
Till now we know that the callback of the useEffect function does not return any statement. However, it can return only 1
type of function that will get executed once the component is unmounted. That function is called a cleanup function.
So, it can be implemented in this way (We also created a variable named timer to store the setInterval() ) :-

The 1st image below shows the output when we are in the About page and
the 2nd image shows the output when we navigate to the Contacts page.

Why shouldn’t we make the useEffect()’s callback an async function ?


Before knowing the reason, lets make an useEffect()’s callback an async function and see what error or warning React throws
us. For this example, I am just making the useEffect()’s callback in the Profie FC as an async function.

Also we have removed the setInterval and the returning of the


cleanup function statement from the useEffect()’s callBack. In the
below image, we can see the warning React throws.
The solution is to just write an async function inside the callback of the useEffect() hook and call that async function inside
the useEffect()’s callback only. You can see the solution in this Link (Also, read it till the end of the 1st part i.e. before :How to
Trigger a Hook Manually”).

When you go through the below links,


you might see this warning mentioned
in those articles, or videos. However,
you might not encounter this warning
maybe because React has removed it.

See this video on cleanup too :- https://www.youtube.com/watch?v=5gCtW7RCtQA&ab_channel=ThapaTechnical


Then this :- https://www.youtube.com/watch?v=aKOQtGLT-Yk&ab_channel=TheNetNinja and
https://www.youtube.com/watch?v=Wu0rVQuawLU&ab_channel=WebDevCody
Then see these 2 links too :- Link1, Link2, Link3

Mistakes every React developer should avoid (Also covers the cleanup) :-
https://www.youtube.com/watch?v=QQYeipc_cik&ab_channel=LamaDev

React follows a one-way data binding i.e. data flow only from parent to child, not reverse, at least in theory. But how to do
the reverse action? See this Link4

Why do we write super(props) and is there a problem in writing just super() ? -> Link5, Link6 (See the 1st answer)

You might also like