Legacy React, Class Components, and Classic Patterns Interview Questions
Table of Contents + β
The source repository also includes a large classic React Q&A section that is still useful for interviews, especially when older codebases or class components are involved. This page keeps those additional questions grouped together instead of mixing them into the modern sections.
This page includes 89 questions in this topic group.
Why should we not update the state directly?
If you try to update the state directly then it wonβt re-render the component.
//Wrongthis.state.message = "Hello world";Instead use setState() method. It schedules an update to a componentβs state object. When state changes, the component responds by re-rendering.
//Correctthis.setState({ message: "Hello World" });Note: You can directly assign to the state object either in constructor or using latest javascriptβs class field declaration syntax.
What is the purpose of callback function as an argument of setState()?
The callback function provided as the second argument to setState is executed after the state has been updated and the component has re-rendered. Because setState() is asynchronous, you cannot reliably perform actions that require the updated state immediately after calling setState. The callback ensures your code runs only after the update and re-render are complete.
Example
this.setState({ name: "Sudheer" }, () => { console.log("The name has been updated and the component has re-rendered.");});When to use the callback?
Use the setState callback when you need to perform an action immediately after the DOM has been updated in response to a state change. i.e, The callback is a reliable way to perform actions after a state update and re-render, especially when the timing is critical due to the asynchronous nature of state updates in React. For example, if you need to interact with the updated DOM, trigger analytics, or perform further computations that depend on the new state or rendered output.
Note
- In modern React (with function components), you can achieve similar effects using the
useEffecthook to respond to state changes. - In class components, you can also use lifecycle methods like
componentDidUpdatefor broader post-update logic. - The
setStatecallback is still useful for one-off actions that directly follow a specific state change.
How do you bind methods or event handlers in JSX callbacks?
There are 3 possible ways to achieve this in class components:
-
Binding in Constructor: In JavaScript classes, the methods are not bound by default. The same rule applies for React event handlers defined as class methods. Normally we bind them in constructor.
class User extends Component {constructor(props) {super(props);this.handleClick = this.handleClick.bind(this);}handleClick() {console.log("SingOut triggered");}render() {return <button onClick={this.handleClick}>SingOut</button>;}} -
Public class fields syntax: If you donβt like to use bind approach then public class fields syntax can be used to correctly bind callbacks. The Create React App enables this syntax by default.
handleClick = () => {console.log("SingOut triggered", this);};<button onClick={this.handleClick}>SingOut</button> -
Arrow functions in callbacks: You can use arrow functions directly in the callbacks.
handleClick() {console.log('SingOut triggered');}render() {return <button onClick={() => this.handleClick()}>SignOut</button>;}
Note: If the callback is passed as prop to child components, those components might do an extra re-rendering. In those cases, it is preferred to go with .bind() or public class fields syntax approach considering performance.
How do you pass a parameter to an event handler or callback?
You can use an arrow function to wrap around an event handler and pass parameters:
<button onClick={() => this.handleClick(id)} />This is an equivalent to calling .bind:
<button onClick={this.handleClick.bind(this, id)} />Apart from these two approaches, you can also pass arguments to a function which is defined as arrow function
<button onClick={this.handleClick(id)} />;handleClick = (id) => () => { console.log("Hello, your ticket number is", id);};What is the use of refs?
The ref is used to return a reference to the element. They should be avoided in most cases, however, they can be useful when you need a direct access to the DOM element or an instance of a component.
How do you create refs?
There are two approaches
-
This is a recently added approach. Refs are created using
React.createRef()method and attached to React elements via therefattribute. In order to use refs throughout the component, just assign the ref to the instance property within constructor.class MyComponent extends React.Component {constructor(props) {super(props);this.myRef = React.createRef();}render() {return <div ref={this.myRef} />;}} -
You can also use ref callbacks approach regardless of React version. For example, the search bar componentβs input element is accessed as follows,
class SearchBar extends Component {constructor(props) {super(props);this.txtSearch = null;this.state = { term: "" };this.setInputSearchRef = (e) => {this.txtSearch = e;};}onInputChange(event) {this.setState({ term: this.txtSearch.value });}render() {return (<inputvalue={this.state.term}onChange={this.onInputChange.bind(this)}ref={this.setInputSearchRef}/>);}}
You can also use refs in function components using closures. Note: You can also use inline ref callbacks even though it is not a recommended approach.
What are forward refs?
Ref forwarding is a feature that lets some components take a ref they receive, and pass it further down to a child.
const ButtonElement = React.forwardRef((props, ref) => ( <button ref={ref} className="CustomButton"> {props.children} </button>));
// Create ref to the DOM button:const ref = React.createRef();<ButtonElement ref={ref}>{"Forward Ref"}</ButtonElement>;Which is preferred option with in callback refs and findDOMNode()?
It is preferred to use callback refs over findDOMNode() API. Because findDOMNode() prevents certain improvements in React in the future.
The legacy approach of using findDOMNode:
class MyComponent extends Component { componentDidMount() { findDOMNode(this).scrollIntoView(); }
render() { return <div />; }}The recommended approach is:
class MyComponent extends Component { constructor(props) { super(props); this.node = createRef(); } componentDidMount() { this.node.current.scrollIntoView(); }
render() { return <div ref={this.node} />; }}Why are String Refs legacy?
If you worked with React before, you might be familiar with an older API where the ref attribute is a string, like ref={'textInput'}, and the DOM node is accessed as this.refs.textInput. We advise against it because string refs have below issues, and are considered legacy. String refs were removed in React v16.
-
They force React to keep track of currently executing component. This is problematic because it makes react module stateful, and thus causes weird errors when react module is duplicated in the bundle.
-
They are not composable - if a library puts a ref on the passed child, the user canβt put another ref on it. Callback refs are perfectly composable.
-
They donβt work with static analysis like Flow. Flow canβt guess the magic that framework does to make the string ref appear on
this.refs, as well as its type (which could be different). Callback refs are friendlier to static analysis. -
It doesnβt work as most people would expect with the βrender callbackβ pattern (e.g.
<DataGrid renderRow={this.renderRow} />)class MyComponent extends Component {renderRow = (index) => {// This won't work. Ref will get attached to DataTable rather than MyComponent:return <input ref={"input-" + index} />;// This would work though! Callback refs are awesome.return <input ref={(input) => (this["input-" + index] = input)} />;};render() {return (<DataTable data={this.props.data} renderRow={this.renderRow} />);}}
What are the different phases of component lifecycle?
The component lifecycle has three distinct lifecycle phases:
-
Mounting: The component is ready to mount in the browser DOM. This phase covers initialization from
constructor(),getDerivedStateFromProps(),render(), andcomponentDidMount()lifecycle methods. -
Updating: In this phase, the component gets updated in two ways, sending the new props and updating the state either from
setState()orforceUpdate(). This phase coversgetDerivedStateFromProps(),shouldComponentUpdate(),render(),getSnapshotBeforeUpdate()andcomponentDidUpdate()lifecycle methods. -
Unmounting: In this last phase, the component is not needed and gets unmounted from the browser DOM. This phase includes
componentWillUnmount()lifecycle method.
Itβs worth mentioning that React internally has a concept of phases when applying changes to the DOM. They are separated as follows
-
Render The component will render without any side effects. This applies to Pure components and in this phase, React can pause, abort, or restart the render.
-
Pre-commit Before the component actually applies the changes to the DOM, there is a moment that allows React to read from the DOM through the
getSnapshotBeforeUpdate(). -
Commit React works with the DOM and executes the final lifecycles respectively
componentDidMount()for mounting,componentDidUpdate()for updating, andcomponentWillUnmount()for unmounting.
React 16.3+ Phases (or an interactive version)
Before React 16.3
What are the lifecycle methods of React?
Before React 16.3
- componentWillMount: Executed before rendering and is used for App level configuration in your root component.
- componentDidMount: Executed after first rendering and here all AJAX requests, DOM or state updates, and set up event listeners should occur.
- componentWillReceiveProps: Executed when particular prop updates to trigger state transitions.
- shouldComponentUpdate: Determines if the component will be updated or not. By default it returns
true. If you are sure that the component doesnβt need to render after state or props are updated, you can return false value. It is a great place to improve performance as it allows you to prevent a re-render if component receives new prop. - componentWillUpdate: Executed before re-rendering the component when there are props & state changes confirmed by
shouldComponentUpdate()which returns true. - componentDidUpdate: Mostly it is used to update the DOM in response to prop or state changes.
- componentWillUnmount: It will be used to cancel any outgoing network requests, or remove all event listeners associated with the component.
React 16.3+
- getDerivedStateFromProps: Invoked right before calling
render()and is invoked on every render. This exists for rare use cases where you need a derived state. Worth reading if you need derived state. - componentDidMount: Executed after first rendering and where all AJAX requests, DOM or state updates, and set up event listeners should occur.
- shouldComponentUpdate: Determines if the component will be updated or not. By default, it returns
true. If you are sure that the component doesnβt need to render after the state or props are updated, you can return a false value. It is a great place to improve performance as it allows you to prevent a re-render if component receives a new prop. - getSnapshotBeforeUpdate: Executed right before rendered output is committed to the DOM. Any value returned by this will be passed into
componentDidUpdate(). This is useful to capture information from the DOM i.e. scroll position. - componentDidUpdate: Mostly it is used to update the DOM in response to prop or state changes. This will not fire if
shouldComponentUpdate()returnsfalse. - componentWillUnmount It will be used to cancel any outgoing network requests, or remove all event listeners associated with the component.
How do you create props proxy for HOC component?
You can add/edit props passed to the component using props proxy pattern like this:
function HOC(WrappedComponent) { return class Test extends Component { render() { const newProps = { title: "New Header", footer: false, showFeatureX: false, showFeatureY: true, };
return <WrappedComponent {...this.props} {...newProps} />; } };}What is context?
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
For example, authenticated users, locale preferences, UI themes need to be accessed in the application by many components.
const { Provider, Consumer } = React.createContext(defaultValue);What is the purpose of using super constructor with props argument?
A child class constructor cannot make use of this reference until the super() method has been called. The same applies to ES6 sub-classes as well. The main reason for passing props parameter to super() call is to access this.props in your child constructors.
Passing props:
class MyComponent extends React.Component { constructor(props) { super(props);
console.log(this.props); // prints { name: 'John', age: 42 } }}Not passing props:
class MyComponent extends React.Component { constructor(props) { super();
console.log(this.props); // prints undefined
// but props parameter is still available console.log(props); // prints { name: 'John', age: 42 } }
render() { // no difference outside constructor console.log(this.props); // prints { name: 'John', age: 42 } }}The above code snippets reveals that this.props is different only within the constructor. It would be the same outside the constructor.
How do you set state with a dynamic key name?
If you are using ES6 or the Babel transpiler to transform your JSX code then you can accomplish this with computed property names.
handleInputChange(event) { this.setState({ [event.target.id]: event.target.value })}What would be the common mistake of function being called every time the component renders?
You need to make sure that function is not being called while passing the function as a parameter.
render() { // Wrong: handleClick is called instead of passed as a reference! return <button onClick={this.handleClick()}>{'Click Me'}</button>}Instead, pass the function itself without parenthesis:
render() { // Correct: handleClick is passed as a reference! return <button onClick={this.handleClick}>{'Click Me'}</button>}What are error boundaries in React v16?
Error boundaries are components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed.
A class component becomes an error boundary if it defines a new lifecycle method called componentDidCatch(error, info) or static getDerivedStateFromError() :
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; }
componentDidCatch(error, info) { // You can also log the error to an error reporting service logErrorToMyService(error, info); }
static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true }; }
render() { if (this.state.hasError) { // You can render any custom fallback UI return <h1>{"Something went wrong."}</h1>; } return this.props.children; }}After that use it as a regular component:
<ErrorBoundary> <MyWidget /></ErrorBoundary>How are error boundaries handled in React v15?
React v15 provided very basic support for error boundaries using unstable_handleError method. It has been renamed to componentDidCatch in React v16.
What is the purpose of render method of react-dom?
This method is used to render a React element into the DOM in the supplied container and return a reference to the component. If the React element was previously rendered into container, it will perform an update on it and only mutate the DOM as necessary to reflect the latest changes.
ReactDOM.render(element, container, [callback])If the optional callback is provided, it will be executed after the component is rendered or updated.
What will happen if you use setState() in constructor?
When you use setState(), then apart from assigning to the object state React also re-renders the component and all its children. You would get error like this: Can only update a mounted or mounting component. So we need to use this.state to initialize variables inside constructor.
Is it good to use setState() in componentWillMount() method?
Yes, it is safe to use setState() inside componentWillMount() method. But at the same it is recommended to avoid async initialization in componentWillMount() lifecycle method. componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state in this method will not trigger a re-render. Avoid introducing any side-effects or subscriptions in this method. We need to make sure async calls for component initialization happened in componentDidMount() instead of componentWillMount().
componentDidMount() { axios.get(`api/todos`) .then((result) => { this.setState({ messages: [...result.data] }) })}What will happen if you use props in initial state?
If the props on the component are changed without the component being refreshed, the new prop value will never be displayed because the constructor function will never update the current state of the component. The initialization of state from props only runs when the component is first created.
The following component wonβt display the updated input value:
class MyComponent extends React.Component { constructor(props) { super(props);
this.state = { records: [], inputValue: this.props.inputValue, }; }
render() { return <div>{this.state.inputValue}</div>; }}Using props inside render method will update the value:
class MyComponent extends React.Component { constructor(props) { super(props);
this.state = { record: [], }; }
render() { return <div>{this.props.inputValue}</div>; }}How you use decorators in React?
You can decorate your class components, which is the same as passing the component into a function. Decorators are flexible and readable way of modifying component functionality.
@setTitle("Profile")class Profile extends React.Component { //....}
/* title is a string that will be set as a document title WrappedComponent is what our decorator will receive when put directly above a component class as seen in the example above*/const setTitle = (title) => (WrappedComponent) => { return class extends React.Component { componentDidMount() { document.title = title; }
render() { return <WrappedComponent {...this.props} />; } };};Note: Decorators are a feature that didnβt make it into ES7, but are currently a stage 2 proposal.
What is CRA and its benefits?
The create-react-app CLI tool allows you to quickly create & run React applications with no configuration step.
Letβs create Todo App using CRA:
# Installation$ npm install -g create-react-app
# Create new project$ create-react-app todo-app$ cd todo-app
# Build, test and run$ npm run build$ npm run test$ npm startIt includes everything we need to build a React app:
- React, JSX, ES6, and Flow syntax support.
- Language extras beyond ES6 like the object spread operator.
- Autoprefixed CSS, so you donβt need -webkit- or other prefixes.
- A fast interactive unit test runner with built-in support for coverage reporting.
- A live development server that warns about common mistakes.
- A build script to bundle JS, CSS, and images for production, with hashes and sourcemaps.
What is the lifecycle methods order in mounting?
The lifecycle methods are called in the following order when an instance of a component is being created and inserted into the DOM.
constructor()static getDerivedStateFromProps()render()componentDidMount()
What are the lifecycle methods going to be deprecated in React v16?
The following lifecycle methods going to be unsafe coding practices and will be more problematic with async rendering.
componentWillMount()componentWillReceiveProps()componentWillUpdate()
Starting with React v16.3 these methods are aliased with UNSAFE_ prefix, and the unprefixed version will be removed in React v17.
What is the purpose of getDerivedStateFromProps() lifecycle method?
The new static getDerivedStateFromProps() lifecycle method is invoked after a component is instantiated as well as before it is re-rendered. It can return an object to update state, or null to indicate that the new props do not require any state updates.
class MyComponent extends React.Component { static getDerivedStateFromProps(props, state) { // ... }}This lifecycle method along with componentDidUpdate() covers all the use cases of componentWillReceiveProps().
What is the purpose of getSnapshotBeforeUpdate() lifecycle method?
The new getSnapshotBeforeUpdate() lifecycle method is called right before DOM updates. The return value from this method will be passed as the third parameter to componentDidUpdate().
class MyComponent extends React.Component { getSnapshotBeforeUpdate(prevProps, prevState) { // ... }}This lifecycle method along with componentDidUpdate() covers all the use cases of componentWillUpdate().
What is the recommended way for naming components?
It is recommended to name the component by reference instead of using displayName.
Using displayName for naming component:
export default React.createClass({ displayName: "TodoApp", // ...});The recommended approach:
export default class TodoApp extends React.Component { // ...}also
const TodoApp = () => { //...};export default TodoApp;What is the recommended ordering of methods in component class?
Recommended ordering of methods from mounting to render stage:
staticmethodsconstructor()getChildContext()componentWillMount()componentDidMount()componentWillReceiveProps()shouldComponentUpdate()componentWillUpdate()componentDidUpdate()componentWillUnmount()- click handlers or event handlers like
onClickSubmit()oronChangeDescription() - getter methods for render like
getSelectReason()orgetFooterContent() - optional render methods like
renderNavigation()orrenderProfilePicture() render()
Why we need to pass a function to setState()?
The reason behind for this is that setState() is an asynchronous operation. React batches state changes for performance reasons, so the state may not change immediately after setState() is called. That means you should not rely on the current state when calling setState()βsince you canβt be sure what that state will be. The solution is to pass a function to setState(), with the previous state as an argument. By doing this you can avoid issues with the user getting the old state value on access due to the asynchronous nature of setState().
Letβs say the initial count value is zero. After three consecutive increment operations, the value is going to be incremented only by one.
// assuming this.state.count === 0this.setState({ count: this.state.count + 1 });this.setState({ count: this.state.count + 1 });this.setState({ count: this.state.count + 1 });// this.state.count === 1, not 3If we pass a function to setState(), the count gets incremented correctly.
this.setState((prevState, props) => ({ count: prevState.count + props.increment,}));// this.state.count === 3 as expected(OR)
Why function is preferred over object for setState()?
React may batch multiple setState() calls into a single update for performance. Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.
This counter example will fail to update as expected:
// Wrongthis.setState({ counter: this.state.counter + this.props.increment,});The preferred approach is to call setState() with function rather than object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument.
// Correctthis.setState((prevState, props) => ({ counter: prevState.counter + props.increment,}));Why is isMounted() an anti-pattern and what is the proper solution?
The primary use case for isMounted() is to avoid calling setState() after a component has been unmounted, because it will emit a warning.
if (this.isMounted()) { this.setState({...})}Checking isMounted() before calling setState() does eliminate the warning, but it also defeats the purpose of the warning. Using isMounted() is a code smell because the only reason you would check is because you think you might be holding a reference after the component has unmounted.
An optimal solution would be to find places where setState() might be called after a component has unmounted, and fix them. Such situations most commonly occur due to callbacks, when a component is waiting for some data and gets unmounted before the data arrives. Ideally, any callbacks should be canceled in componentWillUnmount(), prior to unmounting.
What is the difference between constructor and getInitialState?
You should initialize state in the constructor when using ES6 classes, and getInitialState() method when using React.createClass().
Using ES6 classes:
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { /* initial state */ }; }}Using React.createClass():
const MyComponent = React.createClass({ getInitialState() { return { /* initial state */ }; },});Note: React.createClass() is deprecated and removed in React v16. Use plain JavaScript classes instead.
Can you force a component to re-render without calling setState?
By default, when your componentβs state or props change, your component will re-render. If your render() method depends on some other data, you can tell React that the component needs re-rendering by calling forceUpdate().
component.forceUpdate(callback);It is recommended to avoid all uses of forceUpdate() and only read from this.props and this.state in render().
What is the difference between super() and super(props) in React using ES6 classes?
When you want to access this.props in constructor() then you should pass props to super() method.
Using super(props):
class MyComponent extends React.Component { constructor(props) { super(props); console.log(this.props); // { name: 'John', ... } }}Using super():
class MyComponent extends React.Component { constructor(props) { super(); console.log(this.props); // undefined }}Outside constructor() both will display same value for this.props.
What is the difference between setState() and replaceState() methods?
When you use setState() the current and previous states are merged. replaceState() throws out the current state, and replaces it with only what you provide. Usually setState() is used unless you really need to remove all previous keys for some reason. You can also set state to false/null in setState() instead of using replaceState().
How do you listen to state changes?
The componentDidUpdate lifecycle method will be called when state changes. You can compare provided state and props values with current state and props to determine if something meaningful changed.
componentDidUpdate(object prevProps, object prevState)Note: The previous releases of ReactJS also uses componentWillUpdate(object nextProps, object nextState) for state changes. It has been deprecated in latest releases.
What is the recommended approach of removing an array element in React state?
The better approach is to use Array.prototype.filter() method.
For example, letβs create a removeItem() method for updating the state.
removeItem(index) { this.setState({ data: this.state.data.filter((item, i) => i !== index) })}Is it possible to use React without rendering HTML?
It is possible. Here are the possible options:
render() { return false}render() { return true}render() { return null}React version >=16.0.0:
render() { return []}render() { return ""}React version >=16.2.0:
render() { return <React.Fragment></React.Fragment>}render() { return <></>}React version >=18.0.0:
render() { return undefined}What are the possible ways of updating objects in state?
-
Calling
setState()with an object to merge with state:-
Using
Object.assign()to create a copy of the object:const user = Object.assign({}, this.state.user, { age: 42 });this.setState({ user }); -
Using spread operator:
const user = { ...this.state.user, age: 42 };this.setState({ user });
-
Calling
setState()with a function:this.setState((prevState) => ({user: {...prevState.user,age: 42,},}));
-
What are the approaches to include polyfills in your create-react-app?
There are approaches to include polyfills in create-react-app,
-
Manual import from
core-js:Create a file called (something like)
polyfills.jsand import it into rootindex.jsfile. Runnpm install core-jsoryarn add core-jsand import your specific required features.import "core-js/fn/array/find";import "core-js/fn/array/includes";import "core-js/fn/number/is-nan"; -
Using Polyfill service:
Use the polyfill.io CDN to retrieve custom, browser-specific polyfills by adding this line to
index.html:<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=default,Array.prototype.includes"></script>In the above script we had to explicitly request the
Array.prototype.includesfeature as it is not included in the default feature set.
How do you use https instead of http in create-react-app?
You just need to use HTTPS=true configuration. You can edit your package.json scripts section:
"scripts": { "start": "set HTTPS=true && react-scripts start"}or just run set HTTPS=true && npm start
How do you avoid using relative path imports in create-react-app?
Create a file called .env in the project root and write the import path:
NODE_PATH=src/appAfter that restart the development server. Now you should be able to import anything inside src/app without relative paths.
How do you update a component every second?
You need to use setInterval() to trigger the change, but you also need to clear the timer when the component unmounts to prevent errors and memory leaks.
componentDidMount() { this.interval = setInterval(() => this.setState({ time: Date.now() }), 1000)}
componentWillUnmount() { clearInterval(this.interval)}Why is a component constructor called only once?
Reactβs reconciliation algorithm assumes that without any information to the contrary, if a custom component appears in the same place on subsequent renders, itβs the same component as before, so reuses the previous instance rather than creating a new one.
How do you define constants in React?
You can use ES7 static field to define constant.
class MyComponent extends React.Component { static DEFAULT_PAGINATION = 10;}How do you programmatically trigger click event in React?
You could use the ref prop to acquire a reference to the underlying HTMLInputElement object through a callback, store the reference as a class property, then use that reference to later trigger a click from your event handlers using the HTMLElement.click method.
This can be done in two steps:
-
Create ref in render method:
<input ref={(input) => (this.inputElement = input)} /> -
Apply click event in your event handler:
this.inputElement.click();
How do you make AJAX call and in which component lifecycle methods should I make an AJAX call?
You can use AJAX libraries such as Axios, jQuery AJAX, and the browser built-in fetch. You should fetch data in the componentDidMount() lifecycle method. This is so you can use setState() to update your component when the data is retrieved.
For example, the employees list fetched from API and set local state:
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { employees: [], error: null, }; }
componentDidMount() { fetch("https://api.example.com/items") .then((res) => res.json()) .then( (result) => { this.setState({ employees: result.employees, }); }, (error) => { this.setState({ error }); } ); }
render() { const { error, employees } = this.state; if (error) { return <div>Error: {error.message}</div>; } else { return ( <ul> {employees.map((employee) => ( <li key={employee.name}> {employee.name}-{employee.experience} </li> ))} </ul> ); } }}What are render props?
Render Props is a simple technique for sharing code between components using a prop whose value is a function. The following component uses render prop which returns a React element.
<DataProvider render={(data) => <h1>{`Hello ${data.target}`}</h1>} />Libraries such as React Router and DownShift are using this pattern.
How do you dispatch an action on load?
You can dispatch an action in componentDidMount() method and in render() method you can verify the data.
class App extends Component { componentDidMount() { this.props.fetchData(); }
render() { return this.props.isLoaded ? ( <div>{"Loaded"}</div> ) : ( <div>{"Not Loaded"}</div> ); }}
const mapStateToProps = (state) => ({ isLoaded: state.isLoaded,});
const mapDispatchToProps = { fetchData };
export default connect(mapStateToProps, mapDispatchToProps)(App);How do you use connect() from React Redux?
You need to follow two steps to use your store in your container:
-
Use
mapStateToProps(): It maps the state variables from your store to the props that you specify. -
Connect the above props to your container: The object returned by the
mapStateToPropsfunction is connected to the container. You can importconnect()fromreact-redux.import React from "react";import { connect } from "react-redux";class App extends React.Component {render() {return <div>{this.props.containerData}</div>;}}function mapStateToProps(state) {return { containerData: state.data };}export default connect(mapStateToProps)(App);
What is the purpose of at symbol in the Redux connect decorator?
The @ symbol is in fact a JavaScript expression used to signify decorators. Decorators make it possible to annotate and modify classes and properties at design time.
Letβs take an example setting up Redux without and with a decorator.
-
Without decorator:
import React from "react";import * as actionCreators from "./actionCreators";import { bindActionCreators } from "redux";import { connect } from "react-redux";function mapStateToProps(state) {return { todos: state.todos };}function mapDispatchToProps(dispatch) {return { actions: bindActionCreators(actionCreators, dispatch) };}class MyApp extends React.Component {// ...define your main app here}export default connect(mapStateToProps, mapDispatchToProps)(MyApp); -
With decorator:
import React from "react";import * as actionCreators from "./actionCreators";import { bindActionCreators } from "redux";import { connect } from "react-redux";function mapStateToProps(state) {return { todos: state.todos };}function mapDispatchToProps(dispatch) {return { actions: bindActionCreators(actionCreators, dispatch) };}@connect(mapStateToProps, mapDispatchToProps)export default class MyApp extends React.Component {// ...define your main app here}
The above examples are almost similar except the usage of decorator. The decorator syntax isnβt built into any JavaScript runtimes yet, and is still experimental and subject to change. You can use babel for the decorators support.
How do you use TypeScript in create-react-app application?
Starting from react-scripts@3.3.0+ releases onwards, you can now optionally start a new app from a template by appending --template [template-name] to the creation command. If you donβt select a template, it will create your project with base template. Remember that templates are always named in the format cra-template-[template-name], here you only need to fill the [template-name] section.
The typeScript can be used in your project by appending --template typescript to the creation command.
npx create-react-app my-app --template typescriptBut if you are using React Scripting between react-scripts@2.1.0 and react-scripts@3.2.x , there is a built-in support for TypeScript. i.e, create-react-app now supports TypeScript natively. You can just pass --typescript option as below
npx create-react-app my-app --typescript
# or
yarn create react-app my-app --typescriptWhereas for lower versions of react scripts, just supply --scripts-version option as react-scripts-ts while you create a new project. react-scripts-ts is a set of adjustments to take the standard create-react-app project pipeline and bring TypeScript into the mix.
Now the project layout should look like the following:
my-app/ββ .gitignoreββ images.d.tsββ node_modules/ββ public/ββ src/β ββ ...ββ package.jsonββ tsconfig.jsonββ tsconfig.prod.jsonββ tsconfig.test.jsonββ tslint.jsonDoes the statics object work with ES6 classes in React?
No, statics only works with React.createClass():
someComponent = React.createClass({ statics: { someMethod: function () { // .. }, },});But you can write statics inside ES6+ classes as below,
class Component extends React.Component { static propTypes = { // ... };
static someMethod() { // ... }}or writing them outside class as below,
class Component extends React.Component { ....}
Component.propTypes = {...}Component.someMethod = function(){....}Why are inline ref callbacks or functions not recommended?
If the ref callback is defined as an inline function, it will get called twice during updates, first with null and then again with the DOM element. This is because a new instance of the function is created with each render, so React needs to clear the old ref and set up the new one.
class UserForm extends Component { handleSubmit = () => { console.log("Input Value is: ", this.input.value); };
render() { return ( <form onSubmit={this.handleSubmit}> <input type="text" ref={(input) => (this.input = input)} /> // Access DOM input in handle submit <button type="submit">Submit</button> </form> ); }}But our expectation is for the ref callback to get called once, when the component mounts. One quick fix is to use the ES7 class property syntax to define the function
class UserForm extends Component { handleSubmit = () => { console.log("Input Value is: ", this.input.value); };
setSearchInput = (input) => { this.input = input; };
render() { return ( <form onSubmit={this.handleSubmit}> <input type="text" ref={this.setSearchInput} /> // Access DOM input in handle submit <button type="submit">Submit</button> </form> ); }}What are HOC factory implementations?
There are two main ways of implementing HOCs in React.
- Props Proxy (PP) and
- Inheritance Inversion (II).
But they follow different approaches for manipulating the WrappedComponent.
Props Proxy
In this approach, the render method of the HOC returns a React Element of the type of the WrappedComponent. We also pass through the props that the HOC receives, hence the name Props Proxy.
function ppHOC(WrappedComponent) { return class PP extends React.Component { render() { return <WrappedComponent {...this.props} />; } };}Inheritance Inversion
In this approach, the returned HOC class (Enhancer) extends the WrappedComponent. It is called Inheritance Inversion because instead of the WrappedComponent extending some Enhancer class, it is passively extended by the Enhancer. In this way the relationship between them seems inverse.
function iiHOC(WrappedComponent) { return class Enhancer extends WrappedComponent { render() { return super.render(); } };}How do you use class field declarations syntax in React classes?
React Class Components can be made much more concise using the class field declarations. You can initialize the local state without using the constructor and declare class methods by using arrow functions without the extra need to bind them.
Letβs take a counter example to demonstrate class field declarations for state without using constructor and methods without binding,
class Counter extends Component { state = { value: 0 };
handleIncrement = () => { this.setState((prevState) => ({ value: prevState.value + 1, })); };
handleDecrement = () => { this.setState((prevState) => ({ value: prevState.value - 1, })); };
render() { return ( <div> {this.state.value}
<button onClick={this.handleIncrement}>+</button> <button onClick={this.handleDecrement}>-</button> </div> ); }}Why do you not need error boundaries for event handlers?
Error boundaries do not catch errors inside event handlers.
React doesnβt need error boundaries to recover from errors in event handlers. Unlike the render method and lifecycle methods, the event handlers donβt happen during rendering. So if they throw, React still knows what to display on the screen.
If you need to catch an error inside an event handler, use the regular JavaScript try / catch statement:
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { error: null }; this.handleClick = this.handleClick.bind(this); }
handleClick() { try { // Do something that could throw } catch (error) { this.setState({ error }); } }
render() { if (this.state.error) { return <h1>Caught an error.</h1>; } return <button onClick={this.handleClick}>Click Me</button>; }}Note that the above example is demonstrating regular JavaScript behavior and doesnβt use error boundaries.
What is the difference between try catch block and error boundaries?
Try catch block works with imperative code whereas error boundaries are meant for declarative code to render on the screen.
For example, the try catch block used for below imperative code
try { showButton();} catch (error) { // ...}Whereas error boundaries wrap declarative code as below,
<ErrorBoundary> <MyComponent /></ErrorBoundary>So if an error occurs in a componentDidUpdate method caused by a setState somewhere deep in the tree, it will still correctly propagate to the closest error boundary.
What is the required method to be defined for a class component?
The render() method is the only required method in a class component. i.e, All methods other than render method are optional for a class component.
What are the possible return types of render method?
Here are the list of following types used and return from render method,
- React elements: Elements that instruct React to render a DOM node. It includes html elements such as
<div/>and user defined elements. - Arrays and fragments: Return multiple elements to render as Arrays and Fragments to wrap multiple elements
- Portals: Render children into a different DOM subtree.
- String and numbers: Render both Strings and Numbers as text nodes in the DOM
- Booleans or null: Doesnβt render anything but these types are used to conditionally render content.
What is the main purpose of constructor?
The constructor is mainly used for two purposes,
- To initialize local state by assigning object to this.state
- For binding event handler methods to the instance For example, the below code covers both the above cases,
constructor(props) { super(props); // Don't call this.setState() here! this.state = { counter: 0 }; this.handleClick = this.handleClick.bind(this);}Is it mandatory to define constructor for React component?
No, it is not mandatory. i.e, If you donβt initialize state and you donβt bind methods, you donβt need to implement a constructor for your React component.
Why should not call setState in componentWillUnmount?
You should not call setState() in componentWillUnmount() because once a component instance is unmounted, it will never be mounted again.
What is the purpose of getDerivedStateFromError?
This lifecycle method is invoked after an error has been thrown by a descendant component. It receives the error that was thrown as a parameter and should return a value to update state.
The signature of the lifecycle method is as follows,
static getDerivedStateFromError(error)letβs take error boundary use case with the above lifecycle method for demonstration purpose,
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; }
static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true }; }
render() { if (this.state.hasError) { // You can render any custom fallback UI return <h1>Something went wrong.</h1>; }
return this.props.children; }}What is the methods order when component re-rendered?
An update can be caused by changes to props or state. The following methods are called in the following order when a component is being re-rendered.
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
What are the methods invoked during error handling?
Below methods are called when there is an error during rendering, in a lifecycle method, or in the constructor of any child component.
- static getDerivedStateFromError()
- componentDidCatch()
What is the purpose of unmountComponentAtNode method?
This method is available from react-dom package and it removes 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.
The method signature would be as follows,
ReactDOM.unmountComponentAtNode(container);What are the limitations with HOCs?
Higher-order components come with a few caveats apart from its benefits. Here are the few listed in an order,
-
Donβt use HOCs inside the render method: It is not recommended to apply a HOC to a component within the render method of a component.
render() {// A new version of EnhancedComponent is created on every render// EnhancedComponent1 !== EnhancedComponent2const EnhancedComponent = enhance(MyComponent);// That causes the entire subtree to unmount/remount each time!return <EnhancedComponent />;}The above code impacts on performance by remounting a component that causes the state of that component and all of its children to be lost. Instead, apply HOCs outside the component definition so that the resulting component is created only once.
-
Static methods must be copied over: When you apply a HOC to a component the new component does not have any of the static methods of the original component
// Define a static methodWrappedComponent.staticMethod = function () {/*...*/};// Now apply a HOCconst EnhancedComponent = enhance(WrappedComponent);// The enhanced component has no static methodtypeof EnhancedComponent.staticMethod === "undefined"; // trueYou can overcome this by copying the methods onto the container before returning it,
function enhance(WrappedComponent) {class Enhance extends React.Component {/*...*/}// Must know exactly which method(s) to copy :(Enhance.staticMethod = WrappedComponent.staticMethod;return Enhance;} -
Refs arenβt passed through: For HOCs you need to pass through all props to the wrapped component but this does not work for refs. This is because ref is not really a prop similar to key. In this case you need to use the React.forwardRef API
How do you debug forwardRefs in DevTools?
React.forwardRef accepts a render function as parameter and DevTools uses this function to determine what to display for the ref forwarding component.
For example, If you donβt name the render function or not using displayName property then it will appear as βForwardRefβ in the DevTools,
const WrappedComponent = React.forwardRef((props, ref) => { return <LogProps {...props} forwardedRef={ref} />;});But If you name the render function then it will appear as βForwardRef(myFunction)β
const WrappedComponent = React.forwardRef(function myFunction(props, ref) { return <LogProps {...props} forwardedRef={ref} />;});As an alternative, You can also set displayName property for forwardRef function,
function logProps(Component) { class LogProps extends React.Component { // ... }
function forwardRef(props, ref) { return <LogProps {...props} forwardedRef={ref} />; }
// Give this component a more helpful display name in DevTools. // e.g. "ForwardRef(logProps(MyComponent))" const name = Component.displayName || Component.name; forwardRef.displayName = `logProps(${name})`;
return React.forwardRef(forwardRef);}Is it good to use arrow functions in render methods?
Yes, You can use. It is often the easiest way to pass parameters to callback functions. But you need to optimize the performance while using it.
class Foo extends Component { handleClick() { console.log("Click happened"); } render() { return <button onClick={() => this.handleClick()}>Click Me</button>; }}Note: Using an arrow function in render method creates a new function each time the component renders, which may have performance implications
How do you say that state updates are merged?
When you call setState() in the component, React merges the object you provide into the current state.
For example, letβs take a facebook user with posts and comments details as state variables,
constructor(props) { super(props); this.state = { posts: [], comments: [] }; }Now you can update them independently with separate setState() calls as below,
componentDidMount() { fetchPosts().then(response => { this.setState({ posts: response.posts }); });
fetchComments().then(response => { this.setState({ comments: response.comments }); }); }As mentioned in the above code snippets, this.setState({comments}) updates only comments variable without modifying or replacing posts variable.
How do you pass arguments to an event handler?
During iterations or loops, it is common to pass an extra parameter to an event handler. This can be achieved through arrow functions or bind method.
letβs take an example of user details updated in a grid,
<button onClick={(e) => this.updateUser(userId, e)}>Update User details</button><button onClick={this.updateUser.bind(this, userId)}>Update User details</button>In the both approaches, the synthetic argument e is passed as a second argument. You need to pass it explicitly for arrow functions and it will be passed automatically for bind method.
How do you prevent component from rendering?
You can prevent component from rendering by returning null based on specific condition. This way it can conditionally render component.
function Greeting(props) { if (!props.loggedIn) { return null; }
return <div className="greeting">welcome, {props.name}</div>;}class User extends React.Component { constructor(props) { super(props); this.state = {loggedIn: false, name: 'John'}; }
render() { return ( <div> //Prevent component render if it is not loggedIn <Greeting loggedIn={this.state.loggedIn} /> <UserDetails name={this.state.name}> </div> ); }In the above example, the greeting component skips its rendering section by applying condition and returning null value.
Give an example on How to use context?
Context is designed to share data that can be considered global for a tree of React components.
For example, in the code below lets manually thread through a βthemeβ prop in order to style the Button component.
//Let's create a context with a default theme value "luna"const ThemeContext = React.createContext("luna");// Create App component where it uses provider to pass theme value in the treeclass App extends React.Component { render() { return ( <ThemeContext.Provider value="nova"> <Toolbar /> </ThemeContext.Provider> ); }}// A middle component where you don't need to pass theme prop anymorefunction Toolbar(props) { return ( <div> <ThemedButton /> </div> );}// Let's read theme value in the button component to useclass ThemedButton extends React.Component { static contextType = ThemeContext; render() { return <Button theme={this.context} />; }}How do you use contextType?
ContextType is used to consume the context object. The contextType property can be used in two ways,
-
contextType as property of class: The contextType property on a class can be assigned a Context object created by React.createContext(). After that, you can consume the nearest current value of that Context type using this.context in any of the lifecycle methods and render function.
Letβs assign contextType property on MyClass as below,
class MyClass extends React.Component {componentDidMount() {let value = this.context;/* perform a side-effect at mount using the value of MyContext */}componentDidUpdate() {let value = this.context;/* ... */}componentWillUnmount() {let value = this.context;/* ... */}render() {let value = this.context;/* render something based on the value of MyContext */}}MyClass.contextType = MyContext; -
Static field You can use a static class field to initialize your contextType using public class field syntax.
class MyClass extends React.Component {static contextType = MyContext;render() {let value = this.context;/* render something based on the value */}}
What is a consumer?
A Consumer is a React component that subscribes to context changes. It requires a function as a child which receives current context value as argument and returns a react node. The value argument passed to the function will be equal to the value prop of the closest Provider for this context above in the tree.
Letβs take a simple example,
<MyContext.Consumer> {value => /* render something based on the context value */}</MyContext.Consumer>How do you solve performance corner cases while using context?
The context uses reference identity to determine when to re-render, there are some gotchas that could trigger unintentional renders in consumers when a providerβs parent re-renders.
For example, the code below will re-render all consumers every time the Provider re-renders because a new object is always created for value.
class App extends React.Component { render() { return ( <Provider value={{ something: "something" }}> <Toolbar /> </Provider> ); }}This can be solved by lifting up the value to parent state,
class App extends React.Component { constructor(props) { super(props); this.state = { value: { something: "something" }, }; }
render() { return ( <Provider value={this.state.value}> <Toolbar /> </Provider> ); }}What is the purpose of forward ref in HOCs?
Refs will not get passed through because ref is not a prop. It is handled differently by React just like key. If you add a ref to a HOC, the ref will refer to the outermost container component, not the wrapped component. In this case, you can use Forward Ref API. For example, we can explicitly forward refs to the inner FancyButton component using the React.forwardRef API.
The following HOC logs all props,
function logProps(Component) { class LogProps extends React.Component { componentDidUpdate(prevProps) { console.log("old props:", prevProps); console.log("new props:", this.props); }
render() { const { forwardedRef, ...rest } = this.props;
// Assign the custom prop "forwardedRef" as a ref return <Component ref={forwardedRef} {...rest} />; } }
return React.forwardRef((props, ref) => { return <LogProps {...props} forwardedRef={ref} />; });}Letβs use this HOC to log all props that get passed to our βfancy buttonβ component,
class FancyButton extends React.Component { focus() { // ... }
// ...}export default logProps(FancyButton);Now letβs create a ref and pass it to FancyButton component. In this case, you can set focus to button element.
import FancyButton from "./FancyButton";
const ref = React.createRef();ref.current.focus();<FancyButton label="Click Me" handleClick={handleClick} ref={ref} />;Is ref argument available for all functions or class components?
Regular function or class components donβt receive the ref argument, and ref is not available in props either. The second ref argument only exists when you define a component with React.forwardRef call.
Why do you need additional care for component libraries while using forward refs?
When you start using forwardRef in a component library, you should treat it as a breaking change and release a new major version of your library. This is because your library likely has a different behavior such as what refs get assigned to, and what types are exported. These changes can break apps and other libraries that depend on the old behavior.
How do you create react class components without ES6?
If you donβt use ES6 then you may need to use the create-react-class module instead. For default props, you need to define getDefaultProps() as a function on the passed object. Whereas for initial state, you have to provide a separate getInitialState method that returns the initial state.
var Greeting = createReactClass({ getDefaultProps: function () { return { name: "Jhohn", }; }, getInitialState: function () { return { message: this.props.message }; }, handleClick: function () { console.log(this.state.message); }, render: function () { return <h1>Hello, {this.props.name}</h1>; },});Note: If you use createReactClass then auto binding is available for all methods. i.e, You donβt need to use .bind(this) with in constructor for event handlers.
Is it possible to use react without JSX?
Yes, JSX is not mandatory for using React. Actually it is convenient when you donβt want to set up compilation in your build environment. Each JSX element is just syntactic sugar for calling React.createElement(component, props, ...children).
For example, letβs take a greeting example with JSX,
class Greeting extends React.Component { render() { return <div>Hello {this.props.message}</div>; }}
ReactDOM.render( <Greeting message="World" />, document.getElementById("root"));You can write the same code without JSX as below,
class Greeting extends React.Component { render() { return React.createElement("div", null, `Hello ${this.props.message}`); }}
ReactDOM.render( React.createElement(Greeting, { message: "World" }, null), document.getElementById("root"));How do you create HOC using render props?
You can implement most higher-order components (HOC) using a regular component with a render prop. For example, if you would prefer to have a withMouse HOC instead of a <Mouse> component, you could easily create one using a regular <Mouse> with a render prop.
function withMouse(Component) { return class extends React.Component { render() { return ( <Mouse render={(mouse) => <Component {...this.props} mouse={mouse} />} /> ); } };}This way render props gives the flexibility of using either pattern.
What is react scripts?
The react-scripts package is a set of scripts from the create-react-app starter pack which helps you kick off projects without configuring. The react-scripts start command sets up the development environment and starts a server, as well as hot module reloading.
What are the features of create react app?
Here are the list of some of the features provided by create react app.
- React, JSX, ES6, Typescript and Flow syntax support.
- Autoprefixed CSS
- CSS Reset/Normalize
- A live development server
- A fast interactive unit test runner with built-in support for coverage reporting
- A build script to bundle JS, CSS, and images for production, with hashes and sourcemaps
- An offline-first service worker and a web app manifest, meeting all the Progressive Web App criteria.
What is the purpose of renderToNodeStream method?
The ReactDOMServer#renderToNodeStream method is used to generate HTML on the server and send the markup down on the initial request for faster page loads. It also helps search engines to crawl your pages easily for SEO purposes.
Note: Remember this method is not available in the browser but only server.
How do you get redux scaffolding using create-react-app?
Redux team has provided official redux+js or redux+typescript templates for create-react-app project. The generated project setup includes,
- Redux Toolkit and React-Redux dependencies
- Create and configure Redux store
- React-Redux
<Provider>passing the store to React components - Small βcounterβ example to demo how to add redux logic and React-Redux hooks API to interact with the store from components The following commands need to be executed along with template option as below,
- Javascript template:
npx create-react-app my-app --template redux- Typescript template:
npx create-react-app my-app --template redux-typescriptWhat is state mutation and how to prevent it?
State mutation happens when you try to update the state of a component without actually using setState function. This can happen when you are trying to do some computations using a state variable and unknowingly save the result in the same state variable. This is the main reason why it is advised to return new instances of state variables from the reducers by using Object.assign(, β¦) or spread syntax.
This can cause unknown issues in the UI as the value of the state variable got updated without telling React to check what all components were being affected from this update and it can cause UI bugs.
Ex:
class A extends React.component { constructor(props) { super(props); this.state = { loading: false } }
componentDidMount() { let { loading } = this.state; loading = (() => true)(); // Trying to perform an operation and directly saving in a state variable}How to prevent it: Make sure your state variables are immutable by either enforcing immutability by using plugins like Immutable.js, always using setState to make updates, and returning new instances in reducers when sending updated state values.
Disclaimer
The questions provided in this repository are the summary of frequently asked questions across numerous companies. We cannot guarantee that these questions will actually be asked during your interview process, nor should you focus on memorizing all of them. The primary purpose is for you to get a sense of what some companies might ask - do not get discouraged if you donβt know the answer to all of them β - that is ok!
Good luck with your interview π