DEV Community

Cover image for React Native Interview Handbook — Part 7 of 10: Coding Interview Practice
Amit Kumar
Amit Kumar

Posted on

React Native Interview Handbook — Part 7 of 10: Coding Interview Practice

This is Part 7 of 10, a bonus practice article containing 75 coding interview questions drawn from the React Native Interview Handbook. It covers the implementation tasks commonly used in JavaScript and React Native rounds, from string and array problems to hooks, FlatList, asynchronous work, caching, retries, and native modules.

Complete series

This Dev.to series has five core handbook articles plus five focused practice extras. Open the series page to move through the complete reading order:

  1. Part 1: JavaScript — core handbook, questions 1–120
  2. Part 2: React — core handbook, questions 121–220
  3. Part 3: React Native — core handbook, questions 221–420
  4. Part 4: Performance & Architecture — core handbook, questions 421–560
  5. Part 5: Senior & System Design — core handbook, questions 561–719
  6. Part 6: Output-Based JavaScript Practice — bonus practice article
  7. Part 7: Coding Interview Practice — bonus practice article
  8. Part 8: Code Output Challenges — bonus practice article
  9. Part 9: Current React Native Interview Questions — new high-frequency practice article
  10. Part 10: Project & Production Interviews — senior project ownership and real-production practice

How to answer coding questions

Before coding, clarify inputs, output, edge cases, platform constraints, time complexity, space complexity, cancellation, and test coverage. Start with a correct readable solution, then optimize only when the constraint justifies it.

Topics covered

  • Strings, arrays, maps, sets, recursion, and algorithmic complexity
  • Debounce, throttle, memoization, deep cloning, and polyfills
  • Custom hooks, API state, error boundaries, and React rendering
  • FlatList pagination, pull to refresh, search, and offline retry
  • Promises, timeouts, concurrency limits, and exponential backoff
  • Caching, EventEmitter, Pub/Sub, LRU design, and native module boundaries

Interview coding checklist

  • Confirm assumptions before writing code.
  • State time and space complexity.
  • Handle empty input, invalid input, and duplicate values deliberately.
  • For React Native, discuss loading, errors, cancellation, cleanup, and accessibility.
  • Explain how you would test the solution.

Coding Problems

75 reviewed questions.

🟢 Beginner

1. How do you build a character-frequency map?

Answer
Answer: Iterate characters and increment a count keyed by each character.

Code example:

const freq = (s) =>
  [...s].reduce((m, c) => ((m[c] = (m[c] || 0) + 1), m), {});
Enter fullscreen mode Exit fullscreen mode

2. How do you check whether a string is a palindrome?

Answer
Answer: Normalize the string and compare it with its reverse.

Code example:

const isPalindrome = (s) => {
  s = s.toLowerCase();
  return s === [...s].reverse().join('');
};
Enter fullscreen mode Exit fullscreen mode

3. How do you count vowels in a string?

Answer
Answer: Match vowels case-insensitively and use zero when there is no match.

Code example:

const vowels = (s) => (s.match(/[aeiou]/gi) || []).length;
Enter fullscreen mode Exit fullscreen mode

4. How do you find the largest number in an array?

Answer
Answer: Use Math.max with spread for moderate arrays or scan once for very large arrays.

Code example:

const max = (a) => Math.max(...a);
Enter fullscreen mode Exit fullscreen mode

5. How do you implement a usePrevious hook?

Answer
Answer: Store the current value in a ref after commit and return the ref's previous content during render.

Code example:

const ref = useRef();
useEffect(() => {
  ref.current = value;
}, [value]);
return ref.current;
Enter fullscreen mode Exit fullscreen mode

6. How do you remove duplicates from an array?

Answer
Answer: Create a Set from the array and spread it back into an array. This preserves the first occurrence order.

Code example:

const unique = (a) => [...new Set(a)];
Enter fullscreen mode Exit fullscreen mode

7. How do you reverse a string?

Answer
Answer: Split into characters, reverse, and join; use Array.from or spread when Unicode code points matter.

Code example:

const reverse = (s) => [...s].reverse().join('');
Enter fullscreen mode Exit fullscreen mode

🟡 Intermediate

8. Array.prototype.map polyfill (Medium)?

Answer
Answer: Creates a new array and preserves sparse-array holes.
I include value, index and source arguments, support thisArg, and avoid invoking the callback for missing sparse indexes. A full spec polyfill has additional coercion details.

Code example:

Array.prototype.myMap = function (callback, thisArg) {
  if (this == null) throw new TypeError('Invalid receiver');
  const source = Object(this);
  const length = source.length >>> 0;
  const result = new Array(length);
  for (let i = 0; i < length; i++) {
    if (i in source) {
      result[i] = callback.call(thisArg, source[i], i, source);
    }
  }
  return result;
};
Enter fullscreen mode Exit fullscreen mode

9. Array.prototype.reduce polyfill (Medium)?

Answer
Answer: Matches core reduce behavior, including a missing initial value.
The important edge case is an empty array without an initial value. I also skip sparse holes and pass all four callback arguments.

Code example:

Array.prototype.myReduce = function (callback, initialValue) {
  const source = Object(this);
  const length = source.length >>> 0;
  let index = 0;
  let accumulator;
  if (arguments.length > 1) {
    accumulator = initialValue;
  } else {
    while (index < length && !(index in source)) index++;
    if (index >= length) throw new TypeError('Empty array');
    accumulator = source[index++];
  }
  for (; index < length; index++) {
    if (index in source) {
      accumulator = callback(
        accumulator,
        source[index],
        index,
        source,
      );
    }
  }
  return accumulator;
};
Enter fullscreen mode Exit fullscreen mode

10. Challenge A: useDebounce?

Answer
Answer: Keep a debounced value in state, start a timeout whenever the source value or delay changes, and clear the previous timeout in effect cleanup. The hook returns the last value whose delay completed. Tests should cover rapid changes, delay changes, unmount cleanup, and the initial value.

Code example:

function useDebounce(value, delay = 300) {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const id = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(id);
  }, [value, delay]);
  return debounced;
}
Enter fullscreen mode Exit fullscreen mode

11. Challenge B: Infinite scroll + pull to refresh?

Answer
Answer: Keep initial loading, pagination, and refresh states separate. Guard onEndReached while a page request is active, deduplicate items by stable identifier, and ignore or cancel stale responses. Refresh resets the cursor and replaces data only after the first-page request succeeds, while pagination appends the next confirmed page.

Code example:

const loadMore = () => {
  if (!loadingMore && hasNextPage) fetchNextPage();
};
Enter fullscreen mode Exit fullscreen mode

12. Challenge C: API hook with loading/error?

Answer
Answer: I keep data, error, and loading state in a custom hook, run the supplied fetcher in an effect, abort on cleanup, ignore AbortError, and return the three states to the screen.

Code example:

function useApi(fetcher) {
  const [state, setState] = useState({ loading: true });

  useEffect(() => {
    const controller = new AbortController();
    setState({ loading: true });
    fetcher(controller.signal)
      .then((data) => setState({ data, loading: false }))
      .catch((error) => {
        if (error.name !== 'AbortError')
          setState({ error, loading: false });
      });
    return () => controller.abort();
  }, [fetcher]);

  return state;
}
Enter fullscreen mode Exit fullscreen mode

13. Check a normalized palindrome (Easy)?

Answer
Answer: Expected result: true
Explanation: I clarify whether case, spaces, punctuation and Unicode must be ignored. The two-pointer comparison avoids creating a second reversed string.

Code example:

function isPalindrome(value) {
  const clean = value.toLowerCase().replace(/[^a-z0-9]/g, '');
  let left = 0;
  let right = clean.length - 1;
  while (left < right) {
    if (clean[left++] !== clean[right--]) return false;
  }
  return true;
}
isPalindrome('A man, a plan, a canal: Panama');
Enter fullscreen mode Exit fullscreen mode

14. Check two strings are anagrams without sort (Easy/Medium)?

Answer
Answer: areAnagrams('listen', 'silent') returns true.
This frequency-map solution avoids O(n log n) sorting. I first confirm normalization rules and mention that this exact style has appeared in React Native coding rounds.

Code example:

function areAnagrams(a, b) {
  const left = a.toLowerCase().replace(/\s/g, '');
  const right = b.toLowerCase().replace(/\s/g, '');
  if (left.length !== right.length) return false;
  const counts = new Map();
  for (const char of left) {
    counts.set(char, (counts.get(char) ?? 0) + 1);
  }
  for (const char of right) {
    const next = (counts.get(char) ?? 0) - 1;
    if (next < 0) return false;
    counts.set(char, next);
  }
  return true;
}
Enter fullscreen mode Exit fullscreen mode

15. Debounce search TextInput?

Answer
Answer: Update local text immediately and debounce only the search side effect. Clear the previous timer when text changes, cancel the active request when possible, and ignore stale responses so an older query cannot replace newer results.

Code example:

function SearchInput() {
  const [text, setText] = useState('');
  const query = useDebounce(text, 300);

  useEffect(() => {
    if (query) searchApi(query);
  }, [query]);

  return <TextInput value={text} onChangeText={setText} />;
}
Enter fullscreen mode Exit fullscreen mode

16. Deep clone nested arrays and plain objects (Medium)?

Answer
Answer: Expected result: Returns an independent nested copy and preserves circular references.
Explanation: I state the supported types. JSON stringify is not a true deep clone because it loses undefined, Date, BigInt and circular references. In modern production code, structuredClone may be appropriate.

Code example:

function deepClone(value, seen = new WeakMap()) {
  if (value === null || typeof value !== 'object') return value;
  if (seen.has(value)) return seen.get(value);
  if (value instanceof Date) return new Date(value);
  const copy = Array.isArray(value) ? [] : {};
  seen.set(value, copy);
  for (const key of Reflect.ownKeys(value)) {
    copy[key] = deepClone(value[key], seen);
  }
  return copy;
}
Enter fullscreen mode Exit fullscreen mode

17. Find the first non-repeating character (Easy)?

Answer
Answer: c
The first pass counts; the second preserves original order. I return null explicitly when no unique character exists.

Code example:

function firstUnique(value) {
  const counts = new Map();
  for (const char of value) {
    counts.set(char, (counts.get(char) ?? 0) + 1);
  }
  for (const char of value) {
    if (counts.get(char) === 1) return char;
  }
  return null;
}
firstUnique('aabbcddee');
Enter fullscreen mode Exit fullscreen mode

18. Flatten a nested array without flat() (Medium)?

Answer
Answer: [1, 2, 3, 4, 5]
I explain the recursive base case. For extremely deep input I would use an explicit stack to avoid call-stack overflow.

Code example:

function flatten(values) {
  return values.reduce(
    (result, value) =>
      result.concat(Array.isArray(value) ? flatten(value) : value),
    [],
  );
}
flatten([1, [2, [3, 4]], 5]);
Enter fullscreen mode Exit fullscreen mode

19. Flatten object?

Answer
Answer: Walk the object recursively and build each output key from its parent path and current property. Clarify how arrays, null, dates, separator characters, circular references, and empty containers should be handled.

Code example:

function flatten(object, parent = '', result = {}) {
  for (const [key, value] of Object.entries(object)) {
    const path = parent ? `${parent}.${key}` : key;
    if (value && typeof value === 'object' && !Array.isArray(value)) {
      flatten(value, path, result);
    } else {
      result[path] = value;
    }
  }
  return result;
}
Enter fullscreen mode Exit fullscreen mode

20. Flatten only to a requested depth (Medium)?

Answer
Answer: [1, 2, 3, [4]]
I validate depth in production and preserve remaining nested arrays once depth reaches zero. This exact depth-based variation has appeared in a React Native interview report.

Code example:

function flattenDepth(values, depth = 1) {
  if (depth === 0) return values.slice();
  return values.reduce((result, value) => {
    return result.concat(
      Array.isArray(value) ? flattenDepth(value, depth - 1) : value,
    );
  }, []);
}
flattenDepth([1, [2, [3, [4]]]], 2);
Enter fullscreen mode Exit fullscreen mode

21. Function.prototype.bind polyfill (Medium/Hard)?

Answer
Answer: Returns a function with fixed context and optional partial arguments.
A good bind answer must discuss constructor usage: new should ignore the bound context. A fully spec-compliant implementation also handles metadata and edge cases.

Code example:

Function.prototype.myBind = function (context, ...preset) {
  const target = this;
  function bound(...later) {
    const receiver = this instanceof bound ? this : context;
    return target.apply(receiver, [...preset, ...later]);
  }
  bound.prototype = Object.create(target.prototype);
  return bound;
};
Enter fullscreen mode Exit fullscreen mode

22. Group objects by a property (Easy/Medium)?

Answer
Answer: An object whose keys are professions and values are user arrays.
I define behavior for a missing property. In production I may prefer Map if keys are not strings or if prototype-safe storage matters.

Code example:

function groupBy(items, key) {
  return items.reduce((groups, item) => {
    const group = item[key] ?? 'unknown';
    (groups[group] ??= []).push(item);
    return groups;
  }, {});
}
groupBy(users, 'profession');
Enter fullscreen mode Exit fullscreen mode

23. How do you add a timeout to a Promise?

Answer
Answer: Race the operation against a timer Promise that rejects. Clear the timer in a production helper and cancel the underlying operation when possible.

Code example:

function withTimeout(p, ms) {
  return Promise.race([
    p,
    new Promise((_, reject) =>
      setTimeout(() => reject(new Error('Timeout')), ms),
    ),
  ]);
}
Enter fullscreen mode Exit fullscreen mode

24. How do you check whether two strings are anagrams?

Answer
Answer: Normalize both strings and compare sorted characters, or compare frequency maps for linear time.

Code example:

const anagram = (a, b) =>
  [...a].sort().join('') === [...b].sort().join('');
Enter fullscreen mode Exit fullscreen mode

25. How do you find a missing number from 1 through n?

Answer
Answer: Subtract the array sum from n(n+1)/2, assuming exactly one number is missing and values are valid.

Code example:

const missing = (a, n) =>
  (n * (n + 1)) / 2 - a.reduce((x, y) => x + y, 0);
Enter fullscreen mode Exit fullscreen mode

26. How do you find pairs that sum to a target?

Answer
Answer: Scan once with a Set of prior values; when target minus the current value has been seen, record the pair.

Code example:

function twoSum(a, t) {
  const seen = new Set(),
    out = [];
  for (const n of a) {
    if (seen.has(t - n)) out.push([t - n, n]);
    seen.add(n);
  }
  return out;
}
Enter fullscreen mode Exit fullscreen mode

27. How do you find the first non-repeating character?

Answer
Answer: Build a frequency map, then scan the original string and return the first character with count one.

Code example:

function firstUnique(s) {
  const m = freq(s);
  for (const c of s) if (m[c] === 1) return c;
}
Enter fullscreen mode Exit fullscreen mode

28. How do you find the longest substring without repeating characters?

Answer
Answer: Use a sliding window and map each character to its latest index. Move the left edge past a duplicate and track the maximum width.

Code example:

function longest(s) {
  const seen = new Map();
  let l = 0,
    b = 0;
  for (let r = 0; r < s.length; r++) {
    if ((seen.get(s[r]) ?? -1) >= l) l = seen.get(s[r]) + 1;
    seen.set(s[r], r);
    b = Math.max(b, r - l + 1);
  }
  return b;
}
Enter fullscreen mode Exit fullscreen mode

29. How do you find the maximum subarray sum?

Answer
Answer: Kadane's algorithm tracks the best subarray ending at each index and the best seen overall in O(n) time.

Code example:

function maxSubArray(a) {
  let cur = a[0],
    best = a[0];
  for (let i = 1; i < a.length; i++) {
    cur = Math.max(a[i], cur + a[i]);
    best = Math.max(best, cur);
  }
  return best;
}
Enter fullscreen mode Exit fullscreen mode

30. How do you find the second-largest distinct number?

Answer
Answer: Track the largest and second-largest distinct values in one pass, updating both when a new maximum appears.

Code example:

function secondMax(a) {
  let x = -Infinity,
    y = -Infinity;
  for (const n of a) {
    if (n > x) {
      y = x;
      x = n;
    } else if (n > y && n !== x) y = n;
  }
  return y;
}
Enter fullscreen mode Exit fullscreen mode

31. How do you flatten a nested object?

Answer
Answer: Recursively visit nested plain objects, joining path segments, and assign leaf values to the output.

Code example:

function flattenObj(o, p = '', out = {}) {
  for (const [k, v] of Object.entries(o)) {
    const key = p ? `${p}.${k}` : k;
    if (v && typeof v === 'object' && !Array.isArray(v))
      flattenObj(v, key, out);
    else out[key] = v;
  }
  return out;
}
Enter fullscreen mode Exit fullscreen mode

32. How do you flatten an array of any depth?

Answer
Answer: Use flat(Infinity) or recurse into array elements while accumulating scalar values.

Code example:

const flat = nested.flat(Infinity);
function flatten(a) {
  return a.reduce(
    (r, v) => r.concat(Array.isArray(v) ? flatten(v) : v),
    [],
  );
}
Enter fullscreen mode Exit fullscreen mode

33. How do you group an array of objects by a property?

Answer
Answer: Reduce into an object whose property values are arrays, creating each group on first use.

Code example:

function groupBy(a, k) {
  return a.reduce((m, o) => ((m[o[k]] ??= []).push(o), m), {});
}
Enter fullscreen mode Exit fullscreen mode

34. How do you implement a reusable API hook?

Answer
Answer: Model data, loading, and error; start work in an effect; abort during cleanup; and ignore abort errors.

Code example:

function useApi(fetcher) {
  const [state, setState] = useState({ loading: true });

  useEffect(() => {
    const controller = new AbortController();
    fetcher(controller.signal)
      .then((data) => setState({ data, loading: false }))
      .catch((error) => {
        if (error.name !== 'AbortError')
          setState({ error, loading: false });
      });
    return () => controller.abort();
  }, [fetcher]);

  return state;
}
Enter fullscreen mode Exit fullscreen mode

35. How do you implement a theme provider?

Answer
Answer: Store mode in context, derive theme tokens, expose a toggle, and consume through a focused useTheme hook.

Code example:

<ThemeContext.Provider value={{theme,mode,toggle}}>
Enter fullscreen mode Exit fullscreen mode

36. How do you implement a useDebounce hook?

Answer
Answer: Keep a debounced value in state, start a timeout whenever the source value or delay changes, and clear the previous timeout in effect cleanup. The hook returns the last value whose delay completed. Tests should cover rapid changes, delay changes, unmount cleanup, and the initial value.

Code example:

useEffect(() => {
  const id = setTimeout(() => setDebounced(value), delay);
  return () => clearTimeout(id);
}, [value, delay]);
Enter fullscreen mode Exit fullscreen mode

37. How do you implement a useThrottle hook?

Answer
Answer: Track the last publication time, update immediately when the interval has elapsed, otherwise schedule the remaining delay and clean up that timer.

Code example:

function useThrottle(value, delay) {
  const [throttled, setThrottled] = useState(value);
  const lastRun = useRef(0);

  useEffect(() => {
    const remaining = Math.max(
      0,
      delay - (Date.now() - lastRun.current),
    );
    const id = setTimeout(() => {
      lastRun.current = Date.now();
      setThrottled(value);
    }, remaining);
    return () => clearTimeout(id);
  }, [value, delay]);

  return throttled;
}
Enter fullscreen mode Exit fullscreen mode

38. How do you implement an Error Boundary?

Answer
Answer: Use a class component with getDerivedStateFromError for fallback state and componentDidCatch for reporting.

Code example:

class ErrorBoundary extends React.Component {
  componentDidCatch(e, info) {
    logError(e, info);
  }
}
Enter fullscreen mode Exit fullscreen mode

39. How do you implement debounce for search TextInput?

Answer
Answer: I keep the raw text in state for the input, then debounce that value with a custom useDebounce hook. A second effect depends on the debounced query and calls the API. That way we do not hit the server on every keystroke.

Code example:

<TextInput value={text} onChangeText={setText} />;
Enter fullscreen mode Exit fullscreen mode

40. How do you implement debounce?

Answer
Answer: Keep a timer in a closure, clear it on every call, and schedule the function after the quiet period.

Code example:

function debounce(fn, wait) {
  let t;
  return function (...args) {
    clearTimeout(t);
    t = setTimeout(() => fn.apply(this, args), wait);
  };
}
Enter fullscreen mode Exit fullscreen mode

41. How do you implement deep equality?

Answer
Answer: Return true for identical values, reject incompatible non-objects, compare key counts, then recursively compare corresponding properties. Production code must handle cycles, symbols, prototypes, and special types.

Code example:

function deepEqual(a, b) {
  if (Object.is(a, b)) return true;
  if (!a || !b || typeof a !== 'object' || typeof b !== 'object')
    return false;
  const ka = Object.keys(a),
    kb = Object.keys(b);
  return (
    ka.length === kb.length &&
    ka.every((k) => Object.hasOwn(b, k) && deepEqual(a[k], b[k]))
  );
}
Enter fullscreen mode Exit fullscreen mode

42. How do you implement infinite scroll with pull-to-refresh?

Answer
Answer: Track data, page, refresh, and load-more state; replace data on refresh, append on pagination, guard duplicate requests, and provide stable list keys.

Code example:

<FlatList
  data={items}
  refreshing={refreshing}
  onRefresh={refresh}
  onEndReached={loadMore}
  renderItem={renderItem}
/>;
Enter fullscreen mode Exit fullscreen mode

43. How do you implement memoize?

Answer
Answer: Cache results by an argument key and return the cached value on repeated calls. Real implementations need an appropriate key strategy and eviction policy.

Code example:

function memoize(fn) {
  const c = new Map();
  return (...a) => {
    const k = JSON.stringify(a);
    if (c.has(k)) return c.get(k);
    const v = fn(...a);
    c.set(k, v);
    return v;
  };
}
Enter fullscreen mode Exit fullscreen mode

44. How do you implement once?

Answer
Answer: Keep called and result in a closure. Invoke the target only on the first call and return the stored result thereafter.

Code example:

function once(fn) {
  let called = false,
    result;
  return (...a) => {
    if (!called) {
      called = true;
      result = fn(...a);
    }
    return result;
  };
}
Enter fullscreen mode Exit fullscreen mode

45. How do you implement throttle?

Answer
Answer: Track the last execution time and invoke only when the minimum interval has elapsed.

Code example:

function throttle(fn, wait) {
  let last = 0;
  return function (...args) {
    const now = Date.now();
    if (now - last >= wait) {
      last = now;
      fn.apply(this, args);
    }
  };
}
Enter fullscreen mode Exit fullscreen mode

46. How do you move all zeros to the end of an array?

Answer
Answer: Write nonzero values forward in one pass, then fill the remaining positions with zeros.

Code example:

function moveZeroes(a) {
  let i = 0;
  for (const x of a) if (x !== 0) a[i++] = x;
  while (i < a.length) a[i++] = 0;
  return a;
}
Enter fullscreen mode Exit fullscreen mode

47. How do you run an array of async functions sequentially?

Answer
Answer: Use for...of and await each function before starting the next, collecting results in order.

Code example:

async function sequential(fns) {
  const out = [];
  for (const fn of fns) out.push(await fn());
  return out;
}
Enter fullscreen mode Exit fullscreen mode

48. How do you run-length compress a string?

Answer
Answer: Scan each run of equal characters, append the character and run length, then continue from the next run.

Code example:

function compress(s) {
  let out = '',
    i = 0;
  while (i < s.length) {
    let j = i;
    while (j < s.length && s[j] === s[i]) j++;
    out += s[i] + (j - i);
    i = j;
  }
  return out;
}
Enter fullscreen mode Exit fullscreen mode

49. Implement debounce (Medium)?

Answer
Answer: Expected result: Only the latest call runs after calls stop for delay milliseconds.
Explanation: I preserve this and arguments, and expose cancel for component cleanup. In React Native search, I keep the debounced function reference stable and cancel it on unmount.

Code example:

function debounce(fn, delay) {
  let timer;
  function debounced(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  }
  debounced.cancel = () => clearTimeout(timer);
  return debounced;
}
Enter fullscreen mode Exit fullscreen mode

50. Implement debounce and throttle?

Answer
Answer: Debounce clears the previous timer and schedules a new one, so only the final call after quiet time executes. Throttle tracks last execution or a pending timer so calls occur at most once per interval. I preserve this and arguments, expose cancel when useful, and clean it on component unmount.

Code example:

const debounce = (fn, delay) => {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
};

const throttle = (fn, delay) => {
  let ready = true;
  return (...args) => {
    if (!ready) return;
    ready = false;
    fn(...args);
    setTimeout(() => {
      ready = true;
    }, delay);
  };
};
Enter fullscreen mode Exit fullscreen mode

51. Implement debounce?

Answer
Answer: Return a wrapper that clears the previous timer and schedules the latest call after the delay while preserving this and arguments. A production implementation should define leading and trailing execution and expose cancel and flush behavior.

Code example:

function debounce(fn, delay) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}
Enter fullscreen mode Exit fullscreen mode

52. Implement throttle (Medium)?

Answer
Answer: Expected result: At most one call runs per delay window.
Explanation: This is a leading-only throttle. I explicitly ask whether trailing calls, cancel, flush or maxWait are required because those change the implementation.

Code example:

function throttle(fn, delay) {
  let waiting = false;
  return function (...args) {
    if (waiting) return;
    waiting = true;
    fn.apply(this, args);
    setTimeout(() => {
      waiting = false;
    }, delay);
  };
}
Enter fullscreen mode Exit fullscreen mode

53. Implement throttle?

Answer
Answer: Return a wrapper that runs at most once per interval while preserving this and arguments. Track the last execution and optionally schedule the latest trailing call; define leading, trailing, cancel, and flush semantics before coding.

Code example:

function throttle(fn, delay) {
  let ready = true;
  return function (...args) {
    if (!ready) return;
    ready = false;
    fn.apply(this, args);
    setTimeout(() => {
      ready = true;
    }, delay);
  };
}
Enter fullscreen mode Exit fullscreen mode

54. Implement useDebounce and explain when to use it?

Answer
Answer: useDebounce returns a value only after it has stopped changing for a delay. I use it for search input and validation to avoid one API call per keystroke. Cleanup clears the previous timeout; that reset behavior is the key difference from throttle.

Code example:

function useDebounce(value, delay = 300) {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const id = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(id);
  }, [value, delay]);
  return debounced;
}
Enter fullscreen mode Exit fullscreen mode

55. Reverse a string (Easy)?

Answer
Answer: evitaN tcaeR
I use Array.from instead of split('') because it handles Unicode code points such as many emoji better. A follow-up can ask for an in-place array reversal.

Code example:

function reverseString(value) {
  return Array.from(value).reverse().join('');
}
console.log(reverseString('React Native'));
Enter fullscreen mode Exit fullscreen mode

56. Run async tasks with a concurrency limit (Hard)?

Answer
Answer: Runs no more than limit tasks simultaneously and preserves result order.
I accept task functions rather than already-started Promises so concurrency can actually be controlled. I ask whether one rejection should fail fast or whether all results should be collected.

Code example:

async function runLimited(tasks, limit) {
  if (limit < 1) throw new RangeError('limit must be positive');
  const results = new Array(tasks.length);
  let next = 0;
  async function worker() {
    while (true) {
      const index = next++;
      if (index >= tasks.length) return;
      results[index] = await tasks[index]();
    }
  }
  const workers = Array.from(
    { length: Math.min(limit, tasks.length) },
    worker,
  );
  await Promise.all(workers);
  return results;
}
Enter fullscreen mode Exit fullscreen mode

57. Safely access a nested property by path (Easy/Medium)?

Answer
Answer: Returns the city or Unknown without throwing.
For a fixed known path I prefer optional chaining. A helper is useful for dynamic paths, but production parsing needs clear rules for escaping and unsafe keys.

Code example:

function get(object, path, fallback) {
  const keys = Array.isArray(path)
    ? path
    : path
        .replace(/\[(\w+)\]/g, '.$1')
        .split('.')
        .filter(Boolean);
  let current = object;
  for (const key of keys) {
    if (current == null) return fallback;
    current = current[key];
  }
  return current === undefined ? fallback : current;
}
get(user, 'profile.address.city', 'Unknown');
Enter fullscreen mode Exit fullscreen mode

58. Two Sum?

Answer
Answer: I scan once with a Map from value to index. For each number I check whether target minus that number was already seen; if yes I return both indices. This is O(n) time and O(n) space, better than the O(n squared) nested-loop solution.

Code example:

function twoSum(nums, target) {
  const seen = new Map();
  for (let i = 0; i < nums.length; i++) {
    const need = target - nums[i];
    if (seen.has(need)) return [seen.get(need), i];
    seen.set(nums[i], i);
  }
  return [];
}
Enter fullscreen mode Exit fullscreen mode

59. What is the difference between debounce and throttle?

Answer
Answer: Debounce waits until calls stop for a quiet period; throttle limits execution to at most once per interval. Debounce fits search input, while throttle fits continuous scroll updates.

Code example:

const debouncedSearch = debounce(search, 300);
const throttledScroll = throttle(onScroll, 300);
Enter fullscreen mode Exit fullscreen mode

60. Why is JSON.parse(JSON.stringify(value)) not a general deep clone?

Answer
Answer: It loses undefined and functions, converts Date to string, Map/Set to empty objects, NaN/Infinity to null, throws on BigInt and cycles, and does not preserve prototypes. Prefer structuredClone or a type-aware clone.

Code example:

const source = { missing: undefined, createdAt: new Date() };
const clone = JSON.parse(JSON.stringify(source));
console.log(clone); // createdAt is a string; missing is removed
Enter fullscreen mode Exit fullscreen mode

🔴 Senior

61. How do you expose battery level through a native module?

Answer
Answer: Define a narrow asynchronous typed method, read BatteryManager or the iOS equivalent on the correct queue, resolve a Promise, and expose the generated module contract.

Code example:

const level = await NativeModules.Battery.getLevel();
console.log(`Battery level: ${level}%`);
Enter fullscreen mode Exit fullscreen mode

62. How do you implement Array.prototype.filter?

Answer
Answer: Iterate existing indices, call the predicate with the standard arguments and optional thisArg, and push values whose predicate is truthy.

Code example:

Array.prototype.myFilter = function (cb, thisArg) {
  const out = [];
  for (let i = 0; i < this.length; i++)
    if (i in this && cb.call(thisArg, this[i], i, this))
      out.push(this[i]);
  return out;
};
Enter fullscreen mode Exit fullscreen mode

63. How do you implement Array.prototype.map?

Answer
Answer: Iterate existing indices, call the callback with value, index, and source using the optional thisArg, preserve holes, and return a new array.

Code example:

Array.prototype.myMap = function (cb, thisArg) {
  const out = [];
  for (let i = 0; i < this.length; i++)
    if (i in this) out[i] = cb.call(thisArg, this[i], i, this);
  return out;
};
Enter fullscreen mode Exit fullscreen mode

64. How do you implement Array.prototype.reduce?

Answer
Answer: Use the supplied initial value when present; otherwise find the first existing element or throw for an empty array. Fold remaining existing indices with accumulator, value, index, and source.

Code example:

Array.prototype.myReduce = function (cb, init) {
  let i = 0,
    acc;
  if (arguments.length > 1) acc = init;
  else {
    while (i < this.length && !(i in this)) i++;
    if (i >= this.length) throw TypeError();
    acc = this[i++];
  }
  for (; i < this.length; i++)
    if (i in this) acc = cb(acc, this[i], i, this);
  return acc;
};
Enter fullscreen mode Exit fullscreen mode

65. How do you implement Function.prototype.bind?

Answer
Answer: Capture the target, thisArg, and preset arguments and return a function that applies the target with combined arguments. A production polyfill must also preserve new-constructor behavior.

Code example:

Function.prototype.myBind = function (ctx, ...pre) {
  const fn = this;
  return function (...args) {
    return fn.apply(ctx, [...pre, ...args]);
  };
};
Enter fullscreen mode Exit fullscreen mode

66. How do you implement Promise.all?

Answer
Answer: Normalize each input with Promise.resolve, preserve index order, count fulfillments, resolve when all complete, and reject on the first rejection. Resolve an empty iterable immediately.

Code example:

function promiseAll(ps) {
  return new Promise((resolve, reject) => {
    const a = Array.from(ps),
      r = [];
    if (!a.length) return resolve([]);
    let n = 0;
    a.forEach((p, i) =>
      Promise.resolve(p).then((v) => {
        r[i] = v;
        if (++n === a.length) resolve(r);
      }, reject),
    );
  });
}
Enter fullscreen mode Exit fullscreen mode

67. How do you implement Pub/Sub?

Answer
Answer: Maintain subscriber sets by topic; subscribe adds and returns an unsubscribe function, while publish calls a snapshot of current subscribers.

Code example:

function bus() {
  const m = new Map();
  return {
    subscribe(t, f) {
      const s = m.get(t) || new Set();
      s.add(f);
      m.set(t, s);
      return () => s.delete(f);
    },
    publish(t, v) {
      [...(m.get(t) || [])].forEach((f) => f(v));
    },
  };
}
Enter fullscreen mode Exit fullscreen mode

68. How do you implement a cycle-safe deepClone?

Answer
Answer: Return primitives directly, copy special types, register each source object in a WeakMap before recursing, and clone all own keys so cycles reuse the prior copy.

Code example:

function deepClone(v, m = new WeakMap()) {
  if (v === null || typeof v !== 'object') return v;
  if (m.has(v)) return m.get(v);
  if (v instanceof Date) return new Date(v);
  const out = Array.isArray(v) ? [] : {};
  m.set(v, out);
  for (const k of Reflect.ownKeys(v)) out[k] = deepClone(v[k], m);
  return out;
}
Enter fullscreen mode Exit fullscreen mode

69. How do you implement an EventEmitter?

Answer
Answer: Store listeners by event, let on add and off remove callbacks, emit over a snapshot, and implement once with a wrapper that unsubscribes before invoking.

Code example:

class EventEmitter {
  constructor() {
    this.m = Object.create(null);
  }
  on(e, f) {
    (this.m[e] ??= []).push(f);
    return this;
  }
  off(e, f) {
    this.m[e] = (this.m[e] || []).filter((x) => x !== f);
  }
  emit(e, ...a) {
    (this.m[e] || []).slice().forEach((f) => f(...a));
  }
  once(e, f) {
    const w = (...a) => {
      this.off(e, w);
      f(...a);
    };
    return this.on(e, w);
  }
}
Enter fullscreen mode Exit fullscreen mode

70. How do you implement an LRU cache?

Answer
Answer: Use insertion order in a Map: on get, delete and reinsert the key as most recent; on set, refresh the key and evict the first key when over capacity.

Code example:

class LRU {
  constructor(n = 10) {
    this.n = n;
    this.m = new Map();
  }
  get(k) {
    if (!this.m.has(k)) return;
    const v = this.m.get(k);
    this.m.delete(k);
    this.m.set(k, v);
    return v;
  }
  set(k, v) {
    this.m.delete(k);
    this.m.set(k, v);
    if (this.m.size > this.n)
      this.m.delete(this.m.keys().next().value);
  }
}
Enter fullscreen mode Exit fullscreen mode

71. How do you implement inheritance without class syntax?

Answer
Answer: Call the parent constructor for own fields, set the child prototype to Object.create(parent.prototype), and restore child.prototype.constructor.

Code example:

function Animal(n) {
  this.name = n;
}
Animal.prototype.speak = function () {
  return this.name;
};
function Dog(n) {
  Animal.call(this, n);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Enter fullscreen mode Exit fullscreen mode

72. How do you implement offline retry?

Answer
Answer: Retry eligible transient network failures with bounded exponential backoff and jitter, then persist a replay-safe mutation in an outbox for reconnect.

Code example:

async function retry(request, attempts = 3, baseDelay = 200) {
  try {
    return await request();
  } catch (error) {
    if (attempts <= 1) throw error;
    const delay = baseDelay * 2 ** (3 - attempts);
    await new Promise((resolve) => setTimeout(resolve, delay));
    return retry(request, attempts - 1, baseDelay);
  }
}
Enter fullscreen mode Exit fullscreen mode

73. How do you limit concurrent asynchronous operations?

Answer
Answer: Start a fixed number of worker loops that claim the next index and await its work. Await all workers and store results by original index.

Code example:

async function mapPool(items, limit, worker) {
  const out = [],
    workers = [];
  let i = 0;
  async function run() {
    while (i < items.length) {
      const n = i++;
      out[n] = await worker(items[n], n);
    }
  }
  for (let n = 0; n < Math.min(limit, items.length); n++)
    workers.push(run());
  await Promise.all(workers);
  return out;
}
Enter fullscreen mode Exit fullscreen mode

74. How do you retry a failed Promise with exponential backoff?

Answer
Answer: Loop through a bounded number of attempts, return on success, and after each retryable failure await an exponentially increasing delay before rethrowing the final error.

Code example:

async function retry(fn, n = 3, d = 300) {
  let e;
  for (let i = 0; i < n; i++) {
    try {
      return await fn();
    } catch (x) {
      e = x;
      await new Promise((r) => setTimeout(r, d * 2 ** i));
    }
  }
  throw e;
}
Enter fullscreen mode Exit fullscreen mode

75. LRU cache design?

Answer
Answer: An LRU cache evicts the least recently used item when capacity is exceeded. In JavaScript, Map preserves insertion order, so get deletes and reinserts a key to mark it recent; set removes the oldest map key when over capacity. A production cache also defines TTL, memory limits, and whether undefined is a valid value.

Code example:

class LRUCache {
  constructor(capacity) {
    this.capacity = capacity;
    this.cache = new Map();
  }

  get(key) {
    if (!this.cache.has(key)) return undefined;
    const value = this.cache.get(key);
    this.cache.delete(key);
    this.cache.set(key, value);
    return value;
  }

  set(key, value) {
    this.cache.delete(key);
    this.cache.set(key, value);
    if (this.cache.size > this.capacity) {
      this.cache.delete(this.cache.keys().next().value);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Continue practising

For output-based JavaScript practice, use the React Native JavaScript Output Practice series on Dev.to. For architecture, system design, and behavioral preparation, continue with the Complete React Native Interview Handbook 2026 series.

Top comments (0)