- Basic Example
- Example: of using
props - Example of using
state - Best place for API calls
React Life Cycle: Tell the order in which console will be printed? [Parent -> Child]React Life Cycle: Tell the order in which console will be printed? [Parent -> Child1 & Child2]React Life CycleReact Life Cycle Diagram- Example: Calling
Github API& checking the order of execution as perReact Life Cycle - Comparing the way of writing code in Functional Based Component & Class Based Component.
- Dependency Array case:
- Dependency Array (with 2 dependency):
- setTimeOut in
componentDidMount()(i.e usingcomponentWillUnmount()): - setTimeOut in
useEffect()(i.e usingreturnin useEffect()):
-
Class Based Component ``
import React from "react" class ProfileClassComponent1 extends React.Component { render() { console.log("Inside Class Component") return ( <div> <h3>Profile: Class Component</h3> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p> </div> ) } }Note:
- we can't create class based components without
render()method. - This is the only mandatory method for class based components.
- By using
extends React.Component, we are specifing that it is NOT a Normal Class but a React Component
- we can't create class based components without
-
Funtional Component
const ProfileFunctionalComponent = props => { console.log("Inside Functional Component") return ( <div> <hr /> <h3>Profile: Functional Component</h3> <p>Lorem ipsum dolor sit amet.</p> <hr /> </div> ) } export default ProfileFunctionalComponent -
Using above components:
import React from "react" import ProfileFunctionalComponent from "./ProfileFunctionComponent" import ProfileClassComponent from "./ProfileClassComponent1" const About = () => { return ( <div className="flex-container"> <h2>About</h2> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Aut, adipisci?</p> <ProfileFunctionalComponent/> <ProfileClassComponent" /> </div> ) } export default About
-
Class Based Component
import React from "react" class ProfileClassComponent1 extends React.Component { render() { console.log("Inside Profile Class Component") return ( <div> <h3>Profile: Class Component</h3> <p>NAME: {this.props.name}</p> <p>ADDRESS: {this.props.address}</p> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p> </div> ) } } export default ProfileClassComponent1Note:
this.propsis used to access thepropsin class based components.- Note, we have not used
constructer& we are still usingthis.props
-
Funtional Component
const ProfileFunctionalComponent1 = props => { return ( <div> <hr /> <h3>Profile: Functional Component</h3> <p>NAME: {props.name}</p> <p>ADDRESS: {props.address}</p> <p>Lorem ipsum dolor sit amet.</p> <hr /> </div> ) } export default ProfileFunctionalComponent1 -
Using above components:
import React from "react" import ProfileFunctionalComponent1 from "./ProfileFunctionComponent1" import ProfileClassComponent1 from "./ProfileClassComponent1" const About = () => { return ( <div className="flex-container"> <h2>About</h2> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Aut, adipisci?</p> <ProfileFunctionalComponent1 name="Ram" address="India" /> <ProfileClassComponent1 name="Ram" address="India" /> </div> ) } export default About
-
Class Based Component
import React from "react" class ProfileClassComponent2 extends React.Component { constructor(props) { super(props) this.state = { count1: 11, count2: 22 } } render() { console.log("Inside Profile Class Component") return ( <div className="warning"> <h3>Profile: Class Component</h3> <p>NAME: {this.props.name}</p> <p>ADDRESS: {this.props.address}</p> <p>Count1: {this.state.count1}</p> <p>Count2: {this.state.count2}</p> <button onClick={() => this.setState({ count2: this.state.count2 + 1 })}>Increase</button> <button onClick={() => this.setState({ count2: this.state.count2 - 1 })}>Decrease</button> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p> </div> ) } } export default ProfileClassComponent2Note:
- use
this.state{ stateVariable: value}to create state variable - WE DO NOT MUTATE STATE DIRECTLY (Eg:
this.state = value). - Instead use
this.setState{stateVariable: value}to update state variable
- use
-
Funtional Component
import { useState } from "react" const ProfileFunctionalComponent2 = props => { const [count1] = useState(1) const [count2, setCount2] = useState(2) return ( <div> <hr /> <h3>Profile: Functional Component</h3> <p>NAME: {props.name}</p> <p>ADDRESS1111: {props.address}</p> <p>Count1: {count1}</p> <p>Count2: {count2}</p> <button onClick={() => setCount2(count2 + 1)}>Increment</button> <button onClick={() => setCount2(count2 - 1)}>Decrement</button> <p>Lorem ipsum dolor sit amet.</p> <hr /> </div> ) } export default ProfileFunctionalComponent2 -
Using above components:
import React from "react" import ProfileFunctionalComponent2 from "./ProfileFunctionComponent2" import ProfileClassComponent2 from "./ProfileClassComponent2" import { Outlet } from "react-router-dom" const About = () => { return ( <div className="flex-container"> <h2 className="warning">About</h2> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Aut, adipisci?</p> <Outlet /> <ProfileFunctionalComponent2 name="Ram111" address="India" /> <ProfileClassComponent2 name="Ram" address="India" /> </div> ) } export default About
-
Class Based Component
import React from "react" class ProfileClassComponent2 extends React.Component { constructor(props) { super(props) this.state = { count: 0 } } componentDidMount() { console.log("API CALL inside Class Component") } render() { console.log("Inside Profile Class Component") return ( <div className="warning"> <h3>Profile: Class Component</h3> <p>Count: {this.state.count}</p> </div> ) } } export default ProfileClassComponent2Note:
- componentDidMount() is only called in the initial render.
- React has a Life Cycle Methods that are call:
- First constructor() is called
- then render() is called
- then componentDidMount() is called
-
Funtional Component
import { useState, useEffect } from "react" const ProfileFunctionalComponent3 = props => { const [count] = useState(0) useEffect(() => { console.log("API CALL inside Functional Component") }, []) return ( <div> <hr /> <h3>Profile: Functional Component</h3> <p>Count: {count}</p> <hr /> </div> ) } export default ProfileFunctionalComponent3
-
Class Based Component
About.js(Parent)import React from "react" import ProfileClassComponent from "./ProfileClassComponent4" class AboutClassComponent extends React.Component { constructor() { super() console.log("Parent: constructor()") } componentDidMount() { console.log("Parent: componentDidMount()") } render() { console.log("Parent: render()") return ( <div className="flex-container"> <h2 className="warning">About</h2> <ProfileClassComponent /> </div> ) } } export default AboutClassComponent -
Class Based Component
Profile.js(Children)import React from "react" class ProfileClassComponent4 extends React.Component { constructor(props) { super(props) console.log("Child: Constructor()") } componentDidMount() { console.log("Child: ComponentDidMount()") } render() { console.log("Child: Render()") return ( <div> <h3>Profile: Class Component</h3> <p>Count: 0</p> </div> ) } } export default ProfileClassComponent4 -
Output:
Parent: constructor() Parent: render() Child: Constructor() Child: Render() Child: ComponentDidMount() Parent: componentDidMount()Reason:
- Because react tries to patch up the
render phase, that is why,- Parent: Constructor()
- Parent: Render()
- Child: Constructor()
- Child: Render()
- Then, DOM is UPDATED [i.e displaying some UI to the user Eg: shimmer ]
- Then,
Commit Phaseis completed,- Child: ComponentDidMount()
- Parent: ComponentDidMount()
- Because react tries to patch up the
6. React Life Cycle: Q: Tell the order in which console will be printed? [Parent -> Child1 & Child2]
-
Class Based Component
About.js(Parent)import React from "react" import ProfileClassComponent1 from "./ProfileClassComponent5" import ProfileClassComponent2 from "./ProfileClassComponent6" class AboutClassComponent extends React.Component { constructor() { super() console.log("Parent: constructor()") } componentDidMount() { console.log("Parent: componentDidMount()") } render() { console.log("Parent: render()") return ( <div className="flex-container"> <h2 className="warning">About</h2> <ProfileClassComponent1 /> <ProfileClassComponent2 /> </div> ) } } export default AboutClassComponent -
Class Based Component
Profile1.js(Child-1)import React from "react" class ProfileClassComponent5 extends React.Component { constructor(props) { super(props) console.log("Child-1: Constructor()") } componentDidMount() { console.log("Child-1: ComponentDidMount()") } render() { console.log("Child-1: Render()") return ( <div> <h3>Profile: Class Component [Child 1]</h3> <p>Count: 0</p> </div> ) } } export default ProfileClassComponent5 -
Class Based Component
Profile2.js(Child-2)import React from "react" class ProfileClassComponent6 extends React.Component { constructor(props) { super(props) console.log("Child-2: Constructor()") } componentDidMount() { console.log("Child-2: ComponentDidMount()") } render() { console.log("Child-2: Render()") return ( <div> <h3>Profile: Class Component [Child 2]</h3> <p>Count: 0</p> </div> ) } } export default ProfileClassComponent6 -
Output:
Parent: constructor() Parent: render() Child-1: Constructor() Child-1: Render() Child-2: Constructor() Child-2: Render() Child-1: ComponentDidMount() Child-2: ComponentDidMount() Parent: componentDidMount()Reason:
- Because react tries to patch up the
render phase, that is why,- Parent: constructor()
- Parent: render()
- Child-1: Constructor()
- Child-1: Render()
- Child-2: Constructor()
- Child-2: Render()
- So, react tries to complete the
render phasefor the parent as well as all the children.
- Then, DOM is UPDATED [i.e displaying some UI to the user. Eg: shimmer ]
- Then,
Commit Phaseis completed,- Child-1: ComponentDidMount()
- Child-2: ComponentDidMount()
- Parent: ComponentDidMount()
- Because react tries to patch up the
When react is rendering, then render happens in 2 PHASES: Render Phase & Commit Phase
- In
Render Phase:- first, `constructor() is called &
- then, `render() is called
- In
Commit Phase:- first, react will
update the DOM - then, `componentDidMount() is called
- first, react will
- Reference: (Diagram of React Life Cycle Method)[https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/]
-
Class Based Component
About.js(Parent)import React from "react" import ProfileClassComponent from "./ProfileClassComponent7" class AboutClassComponent extends React.Component { constructor() { super() console.log("Parent: constructor()") } componentDidMount() { console.log("Parent: componentDidMount()") } render() { console.log("Parent: render()") return ( <div className="flex-container"> <h2 className="warning">About</h2> <ProfileClassComponent /> </div> ) } } export default AboutClassComponent -
Class Based Component
Profile.js(Child)import React from "react" class ProfileClassComponent7 extends React.Component { constructor(props) { super(props) console.log("Child: Constructor()") } async componentDidMount() { console.log("Child: ComponentDidMount() - START") const user = "deltanode" const data = await fetch("https://api.github.com/users/" + user) const json = await data.json() console.log(json) console.log("Child: ComponentDidMount() - END") } render() { console.log("Child: Render()") return ( <div> <h3>Profile: Class Component</h3> <p>Count: 1001</p> </div> ) } } export default ProfileClassComponent7 -
Output:
- Parent: constructor() - Parent: render() - Child: Constructor() - Child: Render() - Child: ComponentDidMount() - START - Parent: componentDidMount() - {login: 'deltanode', id: 114831, avatar_url: '...', gravatar_id: '...', …} - Child: ComponentDidMount() - ENDNote:
- As, the
componentDidMount()is a async function. - So, when it will start executing it will console log
Child: ComponentDidMount() - START - After that a API call will be made.
- Then, parent
componentDidMount()will be called. - Now, when the response will be received for the API call then then it will be console logged.
- So, because of async,
Child: ComponentDidMount() - ENDwill be console logged at last.
- As, the
- Never Ever Compare
React Life Cycle Methodwith `Fuctional Component Hooks- Eg: Don't compare
useEffect()withcomponentDidMount()bcz useEffect() is NOT using componentDidMount() behind the seen.
-
Case1: when no array is passed, i.e `useEffect(callback):
- As, we know that
componentDidMount()is called during the initial render only. - Now, there is one more
react life cycle methodknown ascomponentDidUpdate() - This
componentDidUpdate()is called every time after everyre-render
- As, we know that
-
Case1: when dependency array is passed, i.e `useEffect(callback,[someStateVariable]):
- In this case we will be using if & else inside
componentDidMount()&componentDidUpdate(). - So, when there are many dependancy then it become a mess as per the redability.
- In this case we will be using if & else inside
-
In this case we will be using if & else inside
componentDidMount()&componentDidUpdate(). -
So, when there are many dependancy then it become a mess as per the redability.
componentDidUpdate(prevProps, prevState) { if (this.state.count !== prevState.count) { // code } if (this.state.count2 !== prevState.count2) { // code } console.log("Component Did Update"); }
-
Class Based Component
import React from "react" class ProfileClassComponent8 extends React.Component { componentDidMount() { this.timer = setInterval(count => { console.log("Hello") }, 1000) } componentWillUnmount() { clearInterval(this.timer) // Code Clean Up } render() { return ( <div> <h3>Profile: Class Component</h3> <p>Count: 1001</p> </div> ) } } export default ProfileClassComponent8Note:
- We are creating a Single Page Application
- As it has only one page, So,
setIntervalwill continue forever, even after new component is renderend. - Thus, we are writing the clear interval in
componentWillUnmount() - As,
componentWillUnmount()will be called when the component will Unmount. - Reference: (Life Cycle Method)[https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/]
-
Funtion Based Component (useEffect() & return)
import { useState, useEffect } from "react" const ProfileFunctionalComponent4 = props => { const [count] = useState(0) useEffect(() => { // API Call const timer = setInterval(() => { console.log("Hi") }, 1000) return () => { clearInterval(timer) console.log("useEffect Return") } }, []) return ( <div> <hr /> <h3>Profile: Functional Component</h3> <p>Count: {count}</p> <hr /> </div> ) } export default ProfileFunctionalComponent4Note:
- We are creating a Single Page Application (SPA)
- As it has only one page, So,
setIntervalwill continue forever, even after new component is renderend. - Thus, we are writing the clear interval in the
returnof useEffect() - So, when the component will unmount, then
return of useEffect()will be called.
Note:
- Functional Component DOESN'T have
Life Cycle Methods. - It has
HOOKSto achieve the same functionality
DISCLAMER:
- Never compare
Life Cycle Methodsin class component with 'HOOKS' of funtional component. - Eg: Don't say
useEffect()of functional compoment is same ascomponentDIDMount()of class component.