Crack The React Interview
React - Frontend

Crack the React Interview – 20+ Questions with Code snippets | Beginner to Advanced Level

Whether you’re a seasoned developer or just starting your React journey, this post is your go-to resource for honing your interview skills.

To enhance your understanding, each question delves into a pair of opposing concepts. By comparing and contrasting, you’ll grasp two crucial aspects simultaneously, and that will clear your concept.

Let’s elevate your React interview preparation together!

Question 1 – What is React?

React can be used to build web, mobile, and desktop applications, making it a versatile framework for cross-platform development.

Question 2 – What is the difference between ReactJS and React Native?

ReactJS is used to build single-page applications or web applications. You can use html tags like h1, p, div etc. to build UI.

export default function MyApp() {
    return (
        <div>
            <h1>Welcome to GetDifferences</h1>
        </div>
    )
}

React Native is used to build cross-platform mobile applications using Javascript. It provides in-built native components like View, Image, Text etc. to build UI components.

import React from 'react';
import { View, Text } from 'react-native';

export const MyApp => () {
    return (
        <View>
            <Text>Subscribe to the GetDifferences</Text>
        </View>
    )
}

Question 3 – What is the difference between Class Component and Functional Component?

A class component requires you to extend from React.Component and create a render function which returns a React element. You can use a constructor to initialise component state.

import React from "react"
import { ReactNode } from "react"

export class ClassComponent extends React.Component {
    state = {
        message: ''
    }
    constructor(props: any) {
        super(props)
        this.state = {
            message: 'Your first class component.'
        }
    }
    render() {
        return(
            <div>
                <h1>{this.state.message}</h1>
            </div>
        )
    }
}

A functional component is just a plain JavaScript function which accepts props as an argument and returns a React element. You can use useState hooks to handle component state.

import { useState } from "react"

const FunctionalComponent = () => {
    const [message, setMessage] = useState('Learn React');

    return(
        <div>
            <h1>{message}</h1>
        </div>
    )
}

export default FunctionalComponent;

Question 4 – What is the difference between state and props in React?

State is managed within the component. It starts with a default value when the component mounts. State is mutable and can be updated using the setState function.

import { useEffect, useState } from "react"

const StateComponent = () => {
    const [message, setMessage] = useState('');

    useEffect(() => {
        setMessage('State vs Props');
    },[])

    return (
        <div>
            <h2>{message}</h2>
        </div>
    )
}

export default StateComponent;

Props get passed data from a parent to child component. It is immutable and cannot be changed within a component.

const PropsComponent = (props: any) => {
    return(
        <div>
            {props.name}
        </div>
    )
}

export default PropsComponent;

Question 5 – What are controlled and uncontrolled components in React?

A controlled component is a component that is controlled by React state. In a controlled component, you can easily perform instant field validation and form data is handled by React Component.

import { Component } from "react";

class ControlledComponent extends Component {
    state = {
        inputValue: ''
    }

    constructor(props: any) {
        super(props)
        this.state = {
            inputValue: ''
        }
    }

    handleInputChange = (event: any) => {
        this.setState({ inputValue: event.target.value })
    }

    handleSubmit = (event: any) => {
        event.preventDefault();
        console.log("Submitted value:", this.state.inputValue);
    }

    render() {
        return(
            <form onSubmit={this.handleSubmit}>
                <label>
                    Input:
                    <input
                        type="text"
                        value={this.state.inputValue}
                        onChange={this.handleInputChange}
                    >                        
                    </input>
                </label>
                <button type="submit" >Submit</button>
            </form>
        )
    }
}

export default ControlledComponent;

An uncontrolled component is a component that maintains its own internal state. In an uncontrolled component, field validation is not an easy task and form data is handled by DOM itself.

import { Component, createRef } from "react";

class UnControlledComponent extends Component {
    inputRef:any = null;

    constructor(props: any) {
        super(props)
        this.inputRef = createRef();
    }

    handleSubmit = (event: any) => {
        event.preventDefault();
        console.log("Submitted value:", this.inputRef.current.value);
    }

    render() {
        return(
            <form onSubmit={this.handleSubmit}>
                <label>
                    Input:
                    <input
                        type="text"
                        ref={this.inputRef}
                    >                        
                    </input>
                </label>
                <button type="submit" >Submit</button>
            </form>
        )
    }
}

export default UnControlledComponent;   

Question 6 – What are the differences between useMemo and useCallback in React?

useMemo is used to memoize values, which means it remembers the result of an expensive computation so that it doesn’t need to be recalculated every time the component renders.

import React, {useMemo, useState} from 'react';

export function MemoExample() {
    const [count, setCount] = useState(0);

    const memoFunction = useMemo(() => {
        return count * 2;
    }, [count]);

    return (
        <div>
            <p>Count: {count}</p>
            <p>Result: {memoFunction}</p>
            <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
    );
}

useCallback is used to memoize functions, ensuring that the same function instance is retained across renders unless its dependencies change.

import React, {useCallback, useState} from 'react';

export function CallbackExample() {
    const [count, setCount] = useState(0);

    const increment = useCallback(() => {
        setCount((prevCount) => prevCount + 1);
    }, []);

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={increment}>Increment</button>
        </div>
    );
}

Question 7 – What is the difference between Pure Component and Regular Component?

Pure components are components that come with a built-in mechanism to prevent unnecessary re-renders. They perform a shallow comparison of their previous and current props and state to determine whether a re-render is necessary.

import React, {PureComponent} from 'react';

    export class PureClassComponent extends PureComponent {
        render() {
            return <div></div>;
        }
    }
import React from 'react';

const PureFunctionalComponent = React.memo(({value}: any) => {
    return <div>{value}</div>;
});

export default PureFunctionalComponent;

Regular components in React, often referred to as functional components or class components, re-render whenever their parent component or they themselves receive new props or their state changes, regardless of whether the new props or state are different from the previous ones.

import React from 'react';

const RegularComponent = ({value}: any) => {
    return <div>{value}</div>;
};

export default RegularComponent;


Question 8 – What are the differences between React’s ref and forwardRef?

ref is a property that allows you to access the underlying DOM node or React element created by a component.

import React, {Component} from 'react';

class RefComponent extends Component {
    myRef: any = null;

    constructor(props: any) {
        super(props);
        this.myRef = React.createRef();
    }

    componentDidMount() {
        // Accessing the DOM node using ref
        this.myRef.current.focus();
    }

    render() {
        return (
            <input
                type="text"
                ref={this.myRef}
            />
        );
    }
}
export default RefComponent;

forwardRef is a function that creates a React component that can pass its ref to its child component.

import React, {forwardRef, useRef, useEffect} from 'react';

// Child component
const ChildInput = forwardRef((props: any, ref: any) => {
    const inputRef = useRef(null);
    useEffect(() => {
        if (ref) {
            ref.current = inputRef.current;
        }
    }, [ref]);

    return (
        <input
            type="text"
            ref={inputRef}
        />
    );
});

// Parent component
const ParentComponent = () => {
    const inputRef = useRef(null);
    useEffect(() => {
        // Accessing the child component's DOM node using the forwarded ref
        if (inputRef?.current) {
            inputRef?.current?.focus();
        }
    }, []);

    return <ChildInput ref={inputRef} />;
};

export default ParentComponent;

Question 9 – What is the difference between setTimeout and setInterval?

setTimeout is used to execute a function once after a specified delay (in milliseconds).

import React, {useEffect} from 'react';

const SetTimeoutComponent = () => {
    useEffect(() => {
        const timer = setTimeout(() => {
            // This will execute once after 2000 milliseconds (2 seconds)
            console.log('Timeout executed!');
        }, 2000);

        return () => clearTimeout(timer); // Clean up the timer on unmount
    }, []);

    return <div>Timeout Example</div>;
};

export default SetTimeoutComponent;

setInterval is used to repeatedly execute a function at a specified interval.

import React, {useEffect} from 'react';

const SetIntervalCompnent = () => {
    useEffect(() => {
        const interval = setInterval(() => {
            // This code will execute every 1000 milliseconds (1 second)
            console.log('Interval executed!');
        }, 1000);

        return () => clearInterval(interval); // Clean up the interval on unmount
    }, []);

    return <div>Interval Example</div>;
};

export default SetIntervalCompnent;

Question 10 – What is the difference between setInterval and setImmediate?

setInterval is used to repeatedly execute a function at a specified interval.

import React, {useEffect} from 'react';

const SetIntervalCompnent = () => {
    useEffect(() => {
        const interval = setInterval(() => {
            // This code will execute every 1000 milliseconds (1 second)
            console.log('Interval executed!');
        }, 1000);

        return () => clearInterval(interval); // Clean up the interval on unmount
    }, []);

    return <div>Interval Example</div>;
};

export default SetIntervalCompnent;

setImmediate is used to execute a function asynchronously after the current event loop iteration.

import React, {useEffect} from 'react';

const setImmediateComponent = () => {
    useEffect(() => {
        const immediate = setImmediate(() => {
            console.log('setImmediate executed!');
        });

        return () => clearImmediate(immediate); // Cleanup on unmount
    }, []);

    return <div>setImmediate Example</div>;
};

export default setImmediateComponent;

Question 11 – What is the difference between .js, .jsx and .tsx?

.js files contain JavaScript code without any specific JSX or TypeScript syntax.

.jsx files are JavaScript files that contain JSX syntax, allowing for the easy creation of React components.

.tsx files are TypeScript files that contain JSX syntax and allow for static type-checking in addition to JSX, making them suitable for writing React components with type safety.

Question 12 – What is the difference between Redux Action, Reducers and Store?

Actions are payloads of information that describe an intention to change the state.They are plain JavaScript objects with a type property that specifies the type of action to be performed and optional payload data.

const incrementCounter = () => {
    return {
        type: 'INCREMENT_COUNTER',
        payload: {}
    }
}   

Reducers specify how the application’s state changes in response to actions.They are pure functions that take the current state and an action, and return the new state.

const initialState = {
    counter: 0
}

const incrementCounter = (state = initialState, action) => {
    switch(action.type) {
        case 'INCREMENT_COUNTER':
            return {
                ...state,
                counter: state.counter + 1
            };
            default: 
                return state;
    }
}

Store holds the application’s state. It is created by passing the root reducer function to the createStore or configureStore function provided by Redux.

mport {configureStore} from '@reduxjs/toolkit';
import {counterReducer} from './slices/counterSlice';

export const store = configureStore({
    reducer: {
        counter: counterReducer
    }
}) 

Question 13 – How does Redux differ from the Context API in React?

Redux is used for global state management, especially in large applications with complex state requirements, it comes with more features like middleware support and time-travel debugging, but it may introduce more boilerplate code.

// action.js
export const incrementCounter = () => {
    return {
        type: 'INCREMENT_COUNTER'
    }
}

// reducers.js
const CounterReducer = (state = { count: 0}, action: any) => {
    switch(action.type) {
        case 'INCREMENT_COUNTER':
            return {
                ...state,
                counter: state.count + 1
            };
            default: 
                return state;
    }
}

// store.js
import {createStore} from 'redux';
import {combineReducers} from '@reduxjs/toolkit';
import {CounterReducer} from './reducers';

const rootReducer = combineReducers({
    counter: CounterReducer
})
export const store = createStore(rootReducer)

Context API is used when managing local state or when sharing state among components in a specific subtree. It is simpler and more lightweight, making it a good choice for smaller applications or when global state management is not necessary.

import React, {createContext, useState} from 'react';

export const MyContext = createContext(null);

export const MyProvider = ({children}: any) => {
    const [count, setCount] = useState(0);

    const incrementCounter = () => {
        setCount(count + 1);
    };

    return <MyContext.Provider value={{count, incrementCounter}}>
        {children}
    </MyContext.Provider>;
};

Question 14 – How does React.memo() differ from PureComponent in React?

React.memo() is a higher-order component that memoizes a functional component, preventing it from re-rendering if its props have not changed.

import React from 'react';

const ReactMemoComponent = React.memo(({prop1, prop2}: any) => {
    return (
        <div>
            {prop1}
            {prop2}
        </div>
    );
});

export default ReactMemoComponent;

Pure components are components that come with a built-in mechanism to prevent unnecessary re-renders. They perform a shallow comparison of their previous and current props and state to determine whether a re-render is necessary.

import React, {PureComponent} from 'react';

export class PureClassComponent extends PureComponent {
    render() {
        return <div></div>;
    }
}

Question 15 – What are the differences between React Hooks and Higher Order Components (HOCs)?

Hooks are suitable for managing local component state, and designed for functional components. It can lead to cleaner and more readable code by allowing logic to be organized based on its purpose.

import React, {useState, useEffect} from 'react';

function ReactHooksComponent() {
    const [count, setCount] = useState(0);

    useEffect(() => {
        document.title = `Count: ${count}`;
    }, [count]);

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
    );
}

export default ReactHooksComponent;

HOCs are functions that take a component and return a new component with enhanced features. HOCs are traditionally associated with class components.

import React from 'react';

const withLogger = (WrappedComponent: any) => {
    return class extends React.Component {
        componentDidMount() {
            console.log('Component is mounted');
        }

        render() {
            return <WrappedComponent {...this.props} />;
        }
    };
};

class HOCsComponent extends React.Component {
    render() {
        return <div>HOCs Component</div>;
    }
}

const EnhancedComponent = withLogger(HOCsComponent);

Question 16 – What is the difference between imperative and declarative programming in the context of React?

Imperative programming focuses on describing the step-by-step process of achieving a result. It explicitly specifies the sequence of operations to achieve a desired outcome.

const element = document.getElementById('myElement');
element.textContent = 'Imperative Programming';

Declarative programming focuses on describing what result is desired, rather than how to achieve it. Developers declare the desired state or outcome, and the underlying system takes care of the implementation details.

const DeclarativeProgramming  = ({ items }: any) => {
    <ul>
        {
            items.map((item: any, index: number) => {
                <li key={index} >{item}</li>
            })
        }
    </ul>
}

Question 17 – How does React.lazy() differ from using dynamic imports for code splitting in React applications?

React.lazy() is a React-specific method for code splitting. It is used to load a component lazily (on demand) as a separate chunk.

const ReactLazyComponent = React.lazy(() => import('./ReactLazyComponent'));

Dynamic imports using import() is a standard ECMAScript feature, not specific to React. It is used to dynamically load any JavaScript module.

const dynamicModule = import('./dynamicModule');

Question 18 – How does React.Fragment differ from using divs in React components?

Using divs results in an additional div element in the DOM. It may affect styling and layout due to the addition of an extra container.

import React from 'react';

const ComponentWithDivs = () => {
    return (
        <div>
            <h1>Hey</h1>
            <p>Subscribe to the GetDifferences</p>
        </div>
    )
}

Using React.Fragment does not introduce an extra DOM element. It does not contribute any additional styling or layout.

import React from 'react';

const ComponentWithFragment = () => {
    return (
        <React.Fragment>
            <h1>Hey</h1>
            <p>Do not forget to subscribe to our channel.</p>
        </React.Fragment>
    )
}

Question 19 – What is the difference between Shadow DOM and Virtual DOM?

Shadow DOM is focused on encapsulating the styling and behavior of a component. It provides encapsulation by creating scoped and isolated environments for components. Shadow DOM is a native browser feature.

Virtual DOM is focused on optimizing the performance of updates to the actual DOM. It minimizes direct manipulations of the actual DOM to improve the efficiency of updates. Virtual DOM is a concept implemented by libraries like React.

Question 20 – What is the difference between createElement and cloneElement?

The createElement function is used to create a new React element. It takes three arguments: the type of the element (a string or a React component), optional properties (or props) for the element, and any number of additional child elements.

import React from 'react';
import ReactDOM from 'react-dom';

const myElement = React.createElement('div', { className: 'getDifferences'}, 'Hello World!');
ReactDOM.render(myElement, document.getElementById('root'));

The cloneElement function is used to clone a React element and optionally modify its properties. It takes an existing element as its first argument and an object containing the new properties as its second argument.

import React from 'react';
import ReactDOM from 'react-dom';

const originalElement = <div className='getDifference'>Hello, world!</div>
const updatedElement = cloneElement(originalElement, {className: 'updated'});

ReactDOM.render(updatedElement, document.getElementById('root'));

Question 21 – How does server-side rendering (SSR) differ from client-side rendering in React?

In server-side rendering, the server renders the React components on the server and sends the HTML content to the browser. SSR provides faster initial page load times as the HTML is already rendered on the server. SSR is generally better for SEO, as search engines can easily crawl and index the fully-rendered HTML content.

In client-side rendering, the browser downloads a minimal HTML page and renders the React components on the client-side using JavaScript. CSR might result in slower initial load times, especially for larger apps, as it requires the download and execution of JavaScript before rendering. CSR might require additional steps to ensure good SEO.

Question 22 – What are the differences between shallow rendering and full rendering in React testing?

Shallow rendering is a technique where only the component being tested is rendered, and its children are not fully rendered. Execution is faster compared to full rendering since it doesn’t render child components. In React testing, libraries like Enzyme provide a ‘shallow’ method for shallow rendering.

import { shallow } from 'enzyme';
import { MemoExample  } from './components/memoExample';

test('Shallow rendering | shallow', () => {
    const wrapper = shallow(<MemoExample />)
    // perform assertions and tests on the shallow-rendered component.
});

Full rendering involves rendering the entire component tree, including all of its children. It provides a more realistic environment for testing. In React testing, libraries like Enzyme provide a ‘mount’ method for shallow rendering.

import { mount } from 'enzyme';
import { CallbackExample  } from './components/callbackExample';

test('Full rendering | mount', () => {
    const wrapper = mount(<CallbackExample />)
    // perform assertions and tests on the fully-rendered component
    // and its children here
});

Thanks for reading!

If you like our content, please do not forget to subscribe our channel.

Subscribe to our newsletter

Get practical tech insights, cloud & AI tutorials, and real-world engineering tips — delivered straight to your inbox.

No spam. Just useful content for builders.

Leave a Reply

Your email address will not be published. Required fields are marked *