Code Skiller logoCB Logo
Logo LearnLearnLogo PracticePracticeLogo HireHireLogo IDEIDE

React Interview Questions

User image

Published by

sanya sanya

Published at: 9th Dec, 2024
4.75 mins read

1 Implement useUpdateEffect() that it works the same as useEffect() except that it skips running the callback on first render.

import React, { useEffect, useRef, EffectCallback, DependencyList } from 'react'; export function useUpdateEffect(effect: EffectCallback, deps?: DependencyList) { const isFirstRender = useRef(true); useEffect(() => { if (isFirstRender.current) { isFirstRender.current = false; return; } return effect(); }, deps); }

2 Click above header menu on this page, you can see that the dropdown menu is dismissed after clicking outside.

import { useEffect, useRef } from 'react'; export function useClickOutside(callback: () => void) { const ref = useRef<HTMLElement | null>(null); useEffect(() => { function handleClickOutside(event: MouseEvent) { if (ref.current && !ref.current.contains(event.target as Node)) { callback(); } } document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [callback]); return ref; }

3 When we handle async requests in React, we need to pay attention if the component is already unmounted. implement useIsMounted() for us to easily tell if the component is still not unmounted.

import { useEffect, useRef } from 'react'; export function useIsMounted(): () => boolean { const isMountedRef = useRef(false); useEffect(() => { isMountedRef.current = true; return () => { isMountedRef.current = false; }; }, []); return () => isMountedRef.current; }

4 Create a PhoneNumberInput component. only accepts numerical digits format the number automatically as (123)456-7890 by adding the parenthesis when the 4th digit is entered also adding - before 7th digit

import React, { useState } from 'react'; export function PhoneNumberInput() { const [phoneNumber, setPhoneNumber] = useState(''); const handleInputChange = (e) => { let value = e.target.value.replace(/\D/g, ''); // Remove non-numeric characters if (value.length > 10) value = value.slice(0, 10); // Limit input to 10 digits let formattedNumber = value; if (value.length > 3) { formattedNumber = `(${value.slice(0, 3)})${value.slice(3)}`; // Format first part as (XXX) } if (value.length > 6) { formattedNumber = `(${value.slice(0, 3)})${value.slice(3, 6)}-${value.slice(6)}`; // Add a dash for XXX-XXXX } setPhoneNumber(formattedNumber); }; return ( <input data-testid="phone-number-input" value={phoneNumber} onChange={handleInputChange} /> ); }

5 counter starts from 0.

click the '+' button to increment.

click the '-' button to decrement.

import React, { useState } from 'react'; export function App() { const [count, setCount] = useState(0); const increment = () => setCount(count + 1); const decrement = () => setCount(count - 1); return ( <div> <button data-testid="decrement-button" onClick={decrement}>-</button> <button data-testid="increment-button" onClick={increment}>+</button> <p>Clicked: {count}</p> </div> ); }

6 Implement useToggle() to make things easier

import { useState, useCallback } from 'react'; export function useToggle(initialState = false) { const [state, setState] = useState(initialState); const toggle = useCallback(() => { setState((prevState) => !prevState); }, []); return [state, toggle]; } export function App() { const [on, toggle] = useToggle(); return ( <div> <button onClick={toggle}> {on ? 'On' : 'Off'} </button> </div> ); }

7 Create a hook to tell if it is the first render.

import React, { useRef, useEffect } from 'react'; export function useIsFirstRender() { const isFirstRender = useRef(true); useEffect(() => { isFirstRender.current = false; }, []); return isFirstRender.current; } function App() { const isFirstRender = useIsFirstRender(); return ( <div> {isFirstRender ? <p>This is the first render.</p> : <p>This is not the first render.</p>} </div> ); }

8 When array is used in React state, we need to deal with actions such as push and remove. Implement useArray() to make life easier.

Implement useArray() to make life easier. import { useState, useCallback } from 'react'; type UseArrayActions<T> = { push: (item: T) => void; removeByIndex: (index: number) => void; }; export function useArray<T>(initialValue: T[]): { value: T[] } & UseArrayActions<T> { const [array, setArray] = useState<T[]>(initialValue); const push = useCallback((item: T) => { setArray((prevArray) => [...prevArray, item]); }, []); const removeByIndex = useCallback((index: number) => { setArray((prevArray) => prevArray.filter((_, i) => i !== index)); }, []); return { value: array, push, removeByIndex, }; }

9 Create a hook usePrevious() to return the previous value, with initial value of `undefined

export function usePrevious<T>(value: T): T | undefined { const ref = useRef<T | undefined>(undefined); useEffect(() => { ref.current = value; }, [value]); return ref.current; }

10 useTimeout() Create a hook to easily use setTimeout(callback, delay). reset the timer if delay changes DO NOT reset the timer if only callback changes

import { useEffect, useRef } from "react"; export function useTimeout(callback: () => void, delay: number | null) { const savedCallback = useRef(callback); // Keep the latest callback reference updated useEffect(() => { savedCallback.current = callback; }, [callback]); // Set up the timeout if delay is provided useEffect(() => { if (delay === null || delay === undefined) return; const tick = () => savedCallback.current(); const id = setTimeout(tick, delay); return () => clearTimeout(id); }, [delay]); }

11 For a frequently changing value like text input you might want to debounce the changes. Implement useDebounce() to achieve this.

import { useState, useEffect } from 'react'; export function useDebounce<T>(value: T, delay: number): T { const [debouncedValue, setDebouncedValue] = useState(value); useEffect(() => { const handler = setTimeout(() => { setDebouncedValue(value); }, delay); return () => { clearTimeout(handler); }; }, [value, delay]); return debouncedValue; } export function App() { const [value, setValue] = useState(''); const debouncedValue = useDebounce(value, 1000); return ( <div> <input type="text" value={value} onChange={(e) => setValue(e.target.value)} placeholder="Type something..." /> <p>Debounced Value: {debouncedValue}</p> </div> ); }

12 implement useEffectOnce() as the name says itself, it runs an effect only once.

import { useEffect, EffectCallback } from 'react'; export function useEffectOnce(effect: EffectCallback) { useEffect(effect, []); } export function App() { useEffectOnce(() => { console.log('Effect is running only once.'); return () => { console.log('Cleanup on component unmount.'); }; }); return <div>useEffectOnce</div>; }

Library

WEB DEVELOPMENT

Basic

Frontend

Backend

Interview Questions

JavaScript Interview Questions

React Interview Questions

Application Based JS Questions

Basic and Advanced JavaScript Questions

SQL INTERVIEW QUESTIONS

PHP Interview Questions

Python Interview Questions

FAANG QUESTIONS