Practice questions for React Interview:
Higher Order Component in React is defined a component which takes another component as input and may or may not return another component.
For example : Suppose you have two buttons to design – Login & Register – So you can design a button component – then pass it to another higher order component which will have additional functionalities like – styling – on Click – then the text
Hello.jsx
function Hello() {
return <div>Hello</div>;
}
export default Hello;
ContainerHoc.jsx
export default function ContainerHoc(component) {
const Component = component;
return function (props) {
return (
<div>
<h1> Inside HOC</h1>
{/* yahan props pass krna mandatory hai */}
<Component {...props} />
</div>
);
};
}
App.jsx
import "./App.css";
import ContainerHoc from "./components/ContainerHoc";
import Hello from "./components/Hello";
function App() {
const SampleComponent = ContainerHoc(Hello);
return (
<>
<SampleComponent />
</>
);
}
export default App;
In order to work across multiple browsers, react has create a wrapper around native browser events.
- Whenever a event occurs in the application, react listens to it and then wraps the event with an interface - which will provide the same functionality as native browser events.
- Why? By doing so, they have avoided creating multiple implementations for multiple methods for multiple browsers.
Advantages
- Provides cross browser feasibility
- it increases the performance of the application as React reuses the event object.
For Example
Syntax:
e.preventDefault()
prevents all the default behavior by the browser.
e.stopPropagation()
prevents the call to the parent component whenever a child component gets called.
Here ‘e’ is a synthetic event, a cross-browser object. It is made with a wrapper around the actual event of the browser.
function App() {
const onClickHandler = (e) => {
// here e is the synthetic event
console.log(e);
};
return (
<div className="App">
<button onClick={onClickHandler}>Click</button>
</div>
);
}
export default App;
So in react, before the introduction of hooks in 16.8 version - Functional components did not have state - So we had to write class components for any kind of data manipulation through state and props.
-
But after hooks got introducted we got useState(for any kind of state changes) & useEffect for any lifecycle methods.
-
Since functional components are simple Javascript functions so the it is easier to read and test out them, Like useeffect alone can handle 3 lifecycle methods but in class components we have to write three different methods to achieve the scenario
-
Also like class components are internally transformed into functional components only while computation so using fucntional components reduces this extra step of convertion hence we are encouraged to use fucntional componnets over class coponents (** dnm)
-
There is no concept of this - so this is easier to understand and implement.
Strict Mode is a react developer tool (means it only runs in development mode) for identifying possible problems in apllication. It provides deprication checks and warning messages whenever any such code is written in an application.
- Doesn't render any UI, just for development check.
- Since it is a development tool, only works in developement mode - doesn't effect production build whatsoever.
- In order to identify and detect any problems within the application and show warning messages, StrictMode renders every component inside the application twice.
- unsafe lifecycle methods - if a legacy code has unsafe methods , it detects it and shows warnings.
- helpful debugging tool.
- super(props) is used to initialise the parent class constructor - and also by doing this we get to use the this.props
- getDerivedStateFromProps takes state and props as arguments - and is triggered when we want to change the states on basis of props over time. It can return null or new updated state.
- except componentDidMount we should not create sideeffects on any other lifecycle hooks
- render method is the only required method
- order of execution constructor -> getderivedStateFromProps -> render -> componentDidMount
- Update lifecycle methods gets triggered on change of props or state in react component.
- getDerivedStateFromProps -> gets triggered on every re-render -> rarely used
- shouldComponentUpdate -> dictated if at all the component should get rendered or not - by default on change of state or props the component gets re rendered - to prevernt this default behavior we can return false from this method - we can compare the existing state & props with the new state and props and if there is no change we can return false. (performance optimization)
- render () -> returns jsx
- getSnapshotBeforeUpdate -> called right before the changes in thevirtual DOM are to be reflected in the real DOM - takes prevProps and prevState as input- returns a value or null - rarely used
- componentDidUpdate -> called at last - only once - we can make ajax calls -> takes props and state as input -> and snapshot -
- order of execution -> getDerivedStateFromProps ->shouldComponentUpdate -> render -> getSnapshotBeforeUpdate- -> componentDidUpdate
YT
[YT Updating] (https://www.youtube.com/watch?v=DyPkojd1fas&list=PLC3y8-rFHvwgg3vaYJgHGnModB54rxOk3&index=24)
Whenever we face an error in our application , react unmounts the whole component, - in such cases it is always better to show a fallback UI and catch the error.
- A class component that implements either or both the lifecycle methods getDerivedStatefromError & componentDidCatch becomes a error boundary.
- The static method getDerivedStateFromError is used to render a fallback UI after an error is thrown, and the componnetDidCatch method is used to log the error to the console.
Hero.js
import React from "react";
function Hero({ heroName }) {
if (heroName === "Joker") {
throw new Error(" Not a hero!");
}
return <h1>{heroName}</h1>;
}
export default Hero;
ErrorBoundary.js
import React, { Component } from "react";
export class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = {
hasError: false,
};
}
// *takes in error as an argument*
static getDerivedStateFromError(error) {
return { hasError: true };
}
// used to log the error; info is the information related to the error
componentDidCatch(error, info) {
console.log(error);
console.log(info);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;
App.js
import React, { Component } from "react";
import "./App.css";
import Hero from "./components/Hero";
import ErrorBoundary from "./components/ErrorBoundary";
class App extends Component {
render() {
return (
<div className="App">
<Hero heroName="Batman" />
<Hero heroName="Superman" />
// Here we can wrap only the component that is likely to throw an error
or each of the hero components
<ErrorBoundary>
<Hero heroName="Joker" />
</ErrorBoundary>
</div>
);
}
}
export default App;
-
Below will be the output when we wrap each Hero in Error Boundary
-
Error Bounderies can catch errors during rendering, in lifecycle methods and in constructor of the whole tree below them, but can't catch error in event handlers, to catch errors in event handles we need to use try-catch block.
[YT] (https://www.youtube.com/watch?v=DNYXgtZBRPE&list=PLC3y8-rFHvwgg3vaYJgHGnModB54rxOk3&index=32)
The term "render prop" is a technique for sharing code between react components using a prop whose value is a function
- The render name is kind of the convention but we can change it to something else, code will still work.
- Example brief : We have two counters : ClickCounter ( value of count increases on click) & HoverCounter (value increases on hover) - since these are sharing functionalities , we can use renderprops pattern to pass the count and increment count to each.
Below is the container which implements the render props pattern
Counter.js
import React, { Component } from "react";
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
incrementCount = () => {
this.setState((prevState) => {
return { count: prevState.count + 1 };
});
};
render() {
return (
<div>
{this.props.render(this.state.count, this.incrementCount)} // this line
means that it will render whatever is passed to the render prop
</div>
);
}
}
export default Counter;
The below two counters use the props counter and increment counter
ClickCounterTwo.js
import React, { Component } from "react";
class ClickCounterTwo extends Component {
render() {
const { count, incrementCount } = this.props;
return (
<button onClick={incrementCount}>
{this.props.name} Clicked {count} times
</button>
);
}
}
export default ClickCounterTwo;
HoverCounterTwo.js
import React, { Component } from "react";
class HoverCounterTwo extends Component {
render() {
const { count, incrementCount } = this.props;
return <h2 onMouseOver={incrementCount}>Hovered {count} times</h2>;
}
}
export default HoverCounterTwo;
Now in App.js we can use the Counter component and use the "render" prop to pass the count and incrementCount
App.js
import React, { Component } from "react";
import "./App.css";
import Counter from "./components/Counter";
import ClickCounterTwo from "./components/ClickCounterTwo";
import HoverCounterTwo from "./components/HoverCounterTwo";
class App extends Component {
render() {
return (
<div className="App">
<Counter
// in below state we are using the render to pass a function as a prop for the counters
render={(count, incrementCount) => (
<ClickCounterTwo
count={count}
incrementCount={incrementCount}
></ClickCounterTwo>
)}
></Counter>
<Counter
render={(count, incrementCount) => (
<HoverCounterTwo
count={count}
incrementCount={incrementCount}
></HoverCounterTwo>
)}
></Counter>
</div>
);
}
}
export default App;
_Even if they share the count & increment count their instances are different so no conflict will happen. _
React Portals provide a way to render DOM nodes that exists outside the hierarchy of the parent component.
-
In react application, all our components render inside the div with id="root" ; what React Portals provide is the ability to break out of this DOM tree.
-
Step 1: create a div element which has a different id than root - such as portal root `` index.html`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<div id="portal-root"></div> // -> this is the first step to create React Portals
</body>
</html>
- Step 2: create a component - with an UI which we want inside out portal-root div. We have to use ReactDOM.createPortal -> wherein we can pass the string/Component that we want to show as part of the component & second parameter is where we want to place the component in the DOM (in our case portal-root div)
PortalDemo.js
import React from "react";
import ReactDOM from "react-dom";
function PortalDemo() {
return ReactDOM.createPortal(
<h1>Portals Demo</h1>,
document.getElementById("portal-root")
);
}
export default PortalDemo;
- Step 3: Import it where you want to use - (App.js)
App.js
import React, { Component } from "react";
import "./App.css";
import PortalDemo from "./components/PortalDemo";
class App extends Component {
render() {
return (
<div className="App">
<PortalDemo />
</div>
);
}
}
export default App;
-
Use Case: Having to deal with the parent's class's css when the child component is a modal, popup or tooltip
-
Example : CODESANDBOX LINK BY K.C DODDS
-
In the above example the Modal UI will breaks as the parent div has a max width - but if we are using portals , it is fine.
- Eventhough the portal is not inside the React DOM tree, it behaves like a react child in every other way.
- SO an event triggered from inside a portal will propagate to ancestors in React tree(id = "root") even if they are not within the real dom tree. (id = "portal-root")
- Example https://codepen.io/gaearon/pen/jGBWpE
- In the above example the Modal ( which is React portal component) contains a child component with a button click . When we click on the button the even bubbles up in the tree and we are still able to see the clicks count increasing
There are various ways to apply css in react :
- CSS stylesheets
- Inline css
- CSS Modules
- CSS in JS
- There is a file naming convention that we must follow for css module - filename.module.css
- One advantage of using css modules - is that classes are locally scoped by default -
- What the above line means is - suppose we have an app component and an Inner componnet inside app - so if we have a module css file - and we have imported it in app - we can still use it in the Inner component by default (child components have access to the parents css styles) - this leads to css conflicts
- But in css modules since the classes are locally scoped they are not applicable to children component
Inline.js
- No class name bugs: The library generated unique classname for each style. No worries of overlap, or duplication of classnames.
- Easier deletion of css: If we are working on a large codebase, finding the unused css classes bacomes difficult. If a component is not being used - deleting it will delete its styles as well.
- Dynamic styling: In react, since props drive styles - sometimes styles should be modified based on props - styled components allow us to do that.
- Painless Maintenance: It is very easy to maintain the styles when using sc - as we do not have to move across files to access the styles affecting our component.
- Vendor prefixing: For some of the newer css features , we have explicitly write the css property for differnt browsers - but for styled comp - we can write standard css and the rest is handled by the library.
-
- Refs make it possible to access DOM nodes directly within the react component,
- It is a technique to pass a ref through a component to one of its children.
- It is done by using the React.forwardRef function - which revieves a component as an input.
- Every func comp recieves props by default as a parameter , but when we use createRef - we can access the ref as a second attribute
- The "ref" parameter points to the value of the ref attribute of the parent comp.
For example: We have a ref defined in parent component - on click of a button in parent component we want the child input to be focused
FRInput.js
--> child comp
import React from "react";
const FRInput = React.forwardRef((props, ref) => {
return (
<div>
<input type="text" ref={ref} />
</div>
);
});
export default FRInput;
FRParentInput.js
import React, { Component } from "react";
import FRInput from "./FRInput";
export class FRParentInput extends Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
clickHandler = () => {
this.inputRef.current.focus();
};
render() {
return (
<div>
<FRInput ref={this.inputRef} />
<button onClick={this.clickHandler}>Focus Input</button>
</div>
);
}
}
export default FRParentInput;
App.js
import FRParentInput from "./components/FRParentInput";
class App extends Component {
render() {
return (
<div className="App">
<FRParentInput />
</div>
);
}
}
export default App;
The parent comp creates a ref (React.createRef) and attaches it to the child comp.
The child comp recieves the ref as prop and attached it to the native "input" element - such that the parent can now access the native input element.
The child comp forwards the ref from parent to the native inp element.
We can use ref forwarding while dealing with HOC or external library in react.
useRef is a react hook that lets you reference a value that's not needed for rendering. Simply put, when you want to keep a value in a variable that you don't want to rerender you use useRef. The value of useRef is not lost when rerenders happens.
- When we create a ref - we get an object with current property which stores the intial value. {current: 0} --> the output if we console.log(ref) --> so to access the value we have to use ref.current.
Example: UseRef
We have a ref - whose value is 0, and we have counter (state variable ) which also starts with 0. So, if we console.log(Render) in the component - we will see that when we increment the ref, the clg will not get printed, and we wont see any changes in the UI, but when we update the counter (updating the counter re-renders the component), we will see the Ref - with new value.
This means the value of the Ref was persisted all along , but it never caused a rerendered.
In the second example, we have an input and a button and on click of the button we can shift the focus and add a value 5 to the input tag with the help of a ref - As ref allows us to refernce the DOM elements directly.
- Uncontrolled components are those components which are not controlled by React state, and and are handled by the DOM (Document Object Model). So in order to access any value that has been entered we take the help of refs.
- The main problem in uncontrolled components is that the values are not updated automatically.
Uncontrolled.jsx
import React from "react";
export default function Uncontrolled() {
let name = React.createRef();
let age = React.createRef();
const submit = () => {
console.log(name.current.value);
console.log(age.current.value);
};
return (
<>
<div>Uncontrolled</div>
<input type="text" placeholder="name" ref={name} />
<input type="text" placeholder="age" ref={age} />
<button onClick={submit}>Submit</button>
</>
);
}
- Controlled Components are those in which form’s data is handled by the component’s state. It takes its current value through props and makes changes through callbacks like onClick, onChange, etc.
Controlled.jsx
import { useState } from "react";
export default function Controlled() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
function onSubmit() {
console.log("Email value: " + email);
console.log("Password value: " + password);
}
return (
<>
<div>Controlled</div>
<form onSubmit={onSubmit}>
<input
type="email"
name="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<input
type="password"
name="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<input type="submit" value="Submit" />
</form>
</>
);
}
- In a controlled component react, state handles all the form data, whereas, in an uncontrolled component, the HTML form element data is managed by only the DOM.
- If you are using a controlled component, you are in control of your form input values. The developer can decide what to insert or not and where to insert it.
- It is a must to use react state in a controlled component to handle the dynamic form data. It is optional for the uncontrolled component to have a state, but it must use react Ref.
- Controlled components are predictable since the component manages the state of the form elements.
- Because the form elements may change or be impacted by external sources over the lifespan of a component, uncontrolled components are not predictable.
- You can efficiently perform validation tests on each keystroke the user makes by using controlled components. Whatever alters the form components is irrelevant since their values are secure in our local state, where we carry out the validation.
- You can perform validation on the input data only after the form is submitted in the uncontrolled components in react.
useMemo is a react hook that lets you cache the result of a calculation between re-renders.
Example: UseMemoExample
-
In the example, we have 2 states, one to calculate any nth prime number of the number entered in the input (this is a heavy calculation) & another is to toggle the theme. Now we know, that these two states are independant of each other, i.e; the state "number" does not depend on the "isDark" state so if we toggle the dark mode, we should not calculate the prime number.
-
But the issue is React will rerender the component on any state or props change, so even if we toggle the dark mode , the whole component gets rerendered , hence the prime number is again calculated. To avoid this, (since prime number will not change on any toggles of dark mode) - we can cache the result using useMemo.
useCallback is a react hook that lets you cache the function defination in between re-renders.
Example: useCallback In the example we have 2 counters (counter & counter2). And we have 2 buttons increment (for incrementing counter1) & decrement(for decrementing counter2). Now we have a squaredCounter (which displays squared value of the current counter value).
Each time a component gets rendered a new reference to the function is created. So each time counter2 is decremented , a new reference to the squaredValue is created , and since we are printing value of counter2 we can see that in console.
But we don't want that to happen, since squaredValue fnc is solely increasing the value of counter and is not dependent on counter2 we donot want new reference of a function to be generated when counter2 gets updated.
The above can be achieved by using useCallback, the useCallback caches the squaredValue func in between re-renders, so even if the counter2 gets changed, a new refernce of the function is not created. And a new funtion reference gets generated only when counter is changed.
- Custom Hooks are basically Javascript functions - whose name starts with "use".
- Custom Hooks can call other hooks if required.
- We mainly use Custom Hooks to share logic between two or more components - Alternative to HOC & render props.
- We can build our own custom hooks by extracting component logic into resusable functions.
useDocumentTitle Custom Hook
-
The example is that we have two files DocTitleOne & DocTitleTwo - so these are two components which have the same logic as to that they are updating the document title by a counter hence this is reusable logic and we can extract it into a custom hook.
-
Example Video : useDocumentTitle Hook
-
In the below example the reference to the count variable are different - so none of them are effected.
DocTitleOne.js
import React, { useState } from "react";
import useDocumentTitle from "../hooks/useDocumentTitle";
function DocTitleOne() {
const [count, setCount] = useState(0);
useDocumentTitle(count);
return (
<div>
<button onClick={() => setCount(count + 1)}>Count - {count}</button>
</div>
);
}
export default DocTitleOne;
DocTitleTwo.js
import React, { useState } from "react";
import useDocumentTitle from "../hooks/useDocumentTitle";
function DocTitleTwo() {
const [count, setCount] = useState(0);
useDocumentTitle(count);
return (
<div>
<button onClick={() => setCount(count + 1)}>Count - {count}</button>
</div>
);
}
export default DocTitleTwo;
useDocumentTitle.js
import { useEffect } from "react";
function useDocumentTitle(count) {
useEffect(() => {
document.title = `Count ${count}`;
}, [count]);
}
export default useDocumentTitle;
- Updating the state inside the render: If you update the state directly inside your render method or a body of a functional component, it will cause an infinite loop.
function App() {
const [count, setCount] = useState(0);
setCount(1); // infinite loop
return ...
}
We have to use useEffect with an empty array as a dependency.
- Incorrectly set event handlers : We need to provide a function to the onClick, not the result of the function execution. By executing a function before setting a handler, you update a state inside the render, which causes an infinite loop.
export default function App() {
const [count, setCount] = useState(0);
return (
<button onClick={setCount(1)}>Submit</button> // infinite loop
);
}
Set a function to onClick event.
export default function App() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(1)}>Submit</button> // infinite loop
);
}
Below are the list of reasons to prefer fragments over container DOM elements,
- Fragments are a bit faster and use less memory by not creating an extra DOM node. This only has a real benefit on very large and deep trees.
- Some CSS mechanisms like Flexbox and CSS Grid have a special parent-child relationships, and adding divs in the middle makes it hard to keep the desired layout.
- The DOM Inspector is less cluttered.
- React apps generally uses bundlers like webpack to efficiently bundle our code into a minified format- but this doesn't always guarantee optimization
To reduce code time:
- Code-Splitting is a feature supported by Webpack and Browserify, which can create multiple bundles that can be dynamically loaded at runtime.
- One part of this code splitting is to lazy load our apps - react uses lazy and suspense to lazy load our apps
- React.lazy is used to lazy load our components - and while these are loading we can use react.suspense to show UI (like Loading text ...)
- React.suspense has a attribute fallback which can take the any custom comp that we need to display as the UI.
- Whenever our app loads all our routes load at once- but we can load any specific route only when an user navigates to that same.
- We can lazy load our components and wrap our routes in React.suspense
REF
REF
REF
REF
REF
REF
REF
REF
REF
What is the difference between useEffect with empty dependency array and IIFE (Self invoking) function ? Will they do the same thing or different ?
- Below is the interesting answer for this question:
-
The primary difference during the first run is that useEffect with an empty dependency array is specifically designed to handle React component lifecycle events. It allows you to execute code after the initial render, and it provides a clean way to handle cleanup when the component is unmounted.
-
An IIFE, being a general JavaScript pattern, does not have any built-in awareness of React's lifecycle. It will execute immediately, but it doesn't offer the same declarative approach to managing side effects and cleanup associated with React components.
-
One more difference is the IIFE gets executed as soon as it encountered during the code execution process and the useEffect is run after the component has finished mounting as an IIFE runs in a synchronous manner and useEffect runs in an async manner.
REF
REF
REF