This guide is part of a 719-question React Native interview handbook collected from real interviews across startups, product companies, fintech, e-commerce, and MNCs. Questions range from beginner to senior (5+ years) and cover JavaScript, React Native, New Architecture, performance, security, native modules, iOS, Android, system design, and behavioral interviews.
This article contains 120 questions (global questions 1–120). Answer each question before reading the response, explain assumptions and complexity for coding questions, and adapt behavioral examples to your truthful experience.
Difficulty guide
- 🟢 Beginner — expected for entry-level and junior React Native roles.
- 🟡 Intermediate — expected for engineers who can independently ship features.
- 🔴 Senior — tests architecture, trade-offs, production ownership, and native-platform knowledge.
Topics in this part
- JavaScript Fundamentals — 45 questions
- Advanced JavaScript — 22 questions
- ES6+, scope, closures, and async JavaScript — 41 questions
- Promises & Async/Await — 15 questions
- React Fundamentals — questions 1–12
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:
- Part 1: JavaScript — core handbook, questions 1–120
- Part 2: React — core handbook, questions 121–220
- Part 3: React Native — core handbook, questions 221–420
- Part 4: Performance & Architecture — core handbook, questions 421–560
- Part 5: Senior & System Design — core handbook, questions 561–719
- Part 6: Output-Based JavaScript Practice — bonus practice article
- Part 7: Coding Interview Practice — bonus practice article
- Part 8: Code Output Challenges — bonus practice article
- Part 9: Current React Native Interview Questions — new high-frequency practice article
- Part 10: Project & Production Interviews — senior project ownership and real-production practice
Series navigation
Use the Complete React Native Interview Handbook 2026 series page on Dev.to to open every part in order.
Question bank
1. How do &&, ||, ??, ?., and the ternary operator differ?
Answer
Answer: && returns the first falsy operand or last value; || returns the first truthy operand; ?? falls back only for null/undefined; ?. safely accesses nullish values; condition ? a : b chooses one expression.
2. How do find() and filter() differ?
Example:Answer
Answer: find returns the first matching element or undefined. filter returns a new array containing every match, possibly empty.
const users = [{ id: 1 }, { id: 2 }, { id: 2 }];
users.find((x) => x.id === 2); // first matching object
users.filter((x) => x.id === 2); // all matching objects
3. How do function declarations and function expressions differ?
Example:Answer
Answer: Function declarations are initialized during scope creation and can be called earlier in the scope. Expressions are evaluated at their assignment and cannot be called before initialization.
foo();
function foo() {} // works
bar();
const bar = function () {}; // ReferenceError
4. How do includes() and indexOf() differ?
Example:Answer
Answer: includes returns a boolean and can find NaN; indexOf returns the first index or -1 and cannot match NaN.
console.log([NaN].includes(NaN)); // true
console.log([NaN].indexOf(NaN)); // -1
5. How do map(), forEach(), filter(), and reduce() differ?
Example:Answer
Answer: map transforms and returns a same-length array; forEach performs side effects and returns undefined; filter returns all matching elements; reduce combines elements into one result.
console.log([1, 2, 3].map((x) => x * 2)); // [2, 4, 6]
console.log([1, 2, 3].filter((x) => x > 1)); // [2, 3]
console.log([1, 2, 3].reduce((a, x) => a + x, 0)); // 6
6. How do push/pop and shift/unshift differ?
Example:Answer
Answer: push and pop add/remove at the end; unshift and shift add/remove at the front. Front operations generally require reindexing and are more expensive.
const queue = ['A', 'B'];
queue.push('C'); // add at end
queue.pop(); // remove from end
queue.unshift('Z'); // add at front
queue.shift(); // remove from front
7. How do slice() and splice() differ?
Example:Answer
Answer: slice returns a shallow copy of a range without mutating the source. splice mutates the source by deleting, replacing, or inserting elements.
const source = [1, 2, 3];
const copy = source.slice(0, 2); // [1, 2], source unchanged
source.splice(1, 1, 9); // source is [1, 9, 3]
8. What are primitive and reference data types?
Example:Answer
Answer: Primitives are string, number, boolean, null, undefined, symbol, and bigint and are copied by value. Objects, arrays, and functions are reference values, so two variables can point to the same object.
const a = { x: 1 };
const b = a;
b.x = 2; // a.x is 2
9. What does typeof null return?
Answer
Answer: It returns 'object', a historical language bug; null is still a primitive.
10. What happens when two variables reference the same object and one mutates it?
Example:Answer
Answer: Both variables observe the mutation because they reference the same object.
let a = {};
let b = a;
b.name = 'React Native';
console.log(a.name); // 'React Native'
11. What is JavaScript?
Answer
Answer: JavaScript is a high-level, dynamically typed, multi-paradigm language with prototype-based inheritance. It runs in browsers, servers, and React Native engines and commonly uses a single-threaded event loop per runtime context.
12. What is NaN, and how should it be checked?
Example:Answer
Answer: NaN means an invalid numeric result; surprisingly typeof NaN is 'number' and NaN is unequal to itself. Use Number.isNaN to test it without coercion.
typeof NaN; // 'number'
NaN === NaN; // false
Number.isNaN(NaN); // true
13. What is destructuring in JavaScript?
Example:Answer
Answer: Destructuring extracts object properties or array positions into variables and also works in parameters.
const { name, age } = user;
const [first, second] = list;
function greet({ name }) {
return `Hello, ${name}`;
}
14. What is the difference between == and ===?
Example:Answer
Answer: == performs type coercion before comparison; === compares type and value without coercion. Prefer === because coercion can produce surprising results; == null is occasionally used intentionally to match both null and undefined.
5 == '5' // true
5 === '5' // false
[] == false // true
15. What is the difference between null and undefined?
Example:Answer
Answer: undefined usually means a value was not assigned or is missing. null is an intentional empty value assigned by the developer. typeof null returning 'object' is a historical quirk.
let x; // undefined
let user = null; // intentionally empty
16. What is the difference between prefix and postfix increment?
Example:Answer
Answer: Both increment the variable, but ++i evaluates to the new value while i++ evaluates to the old value.
let i = 1;
console.log(i++); // 1, i is 2
let j = 1;
console.log(++j); // 2
17. What is the difference between var, let, and const?
Example:Answer
Answer: var is function-scoped and initialized to undefined when hoisted. let and const are block-scoped and stay in the temporal dead zone until declared; let can be reassigned, while const cannot. Prefer const, use let when reassignment is needed, and avoid var.
const user = { name: 'Ada' };
user.name = 'Bob'; // allowed
for (var i = 0; i < 3; i++) setTimeout(() => console.log(i)); // 3,3,3
for (let i = 0; i < 3; i++) setTimeout(() => console.log(i)); // 0,1,2
18. What is type coercion?
Answer
Answer: Type coercion is implicit or explicit conversion between types. Operators such as loose equality and + may coerce operands, so explicit conversion and strict equality are usually clearer.
19. Which JavaScript values are falsy?
Answer
Answer: The falsy values are false, 0, -0, 0n, an empty string, null, undefined, and NaN. Every other value, including [] and {}, is truthy.
🟡 Intermediate
20. Can arrow functions be used as constructors?
Example:Answer
Answer: No. Arrow functions have no [[Construct]] method or prototype for instances, so calling one with new throws TypeError.
const A = () => {};
new A(); // TypeError
21. Curry a fixed-arity function (Medium)?
Example:Answer
Answer: Expected result: 6
Explanation: Currying converts one multi-argument function into a chain of partially applicable functions. I mention that fn.length has limitations with default and rest parameters.
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
}
return (...next) => curried.apply(this, [...args, ...next]);
};
}
const add = curry((a, b, c) => a + b + c);
add(1)(2)(3);
22. Function declaration vs function expression?
Answer
Answer: A function declaration is hoisted with its function body, so it can be called before its source line. A function expression is created when its assignment executes; with let or const it cannot be used before initialization. Prefer declarations for named reusable functions and expressions for callbacks.
23. Global variable vs local state vs global store?
Answer
Answer: A global variable has no React subscription and can cause stale UI, shared-test leakage, and uncontrolled lifetime. Local state belongs near the component that uses it. A global store is appropriate when unrelated screens need coordinated updates. I keep state local by default and promote it only when sharing, persistence, or cross-feature workflows justify it.
24. How can you clone a nested object?
Example:Answer
Answer: Use structuredClone for supported data, a cycle-aware recursive clone, or a library such as cloneDeep. JSON stringify/parse is only safe for JSON-compatible values.
const copy = structuredClone(value);
25. How do Object.freeze() and Object.seal() differ?
Answer
Answer: seal prevents adding, deleting, or reconfiguring properties but permits writes to writable properties. freeze adds protection against changing existing values. Both are shallow.
26. How do arrow functions and normal functions differ?
Answer
Answer: Arrow functions are concise and lexically capture this; they have no own this, arguments, super, or new.target and cannot be constructors. Normal functions receive this from the call site and can be used with new.
27. How do the in operator and Object.hasOwn() differ?
Example:Answer
Answer: in checks both own and inherited properties. Object.hasOwn checks only an object's own property and is safe even for null-prototype objects.
'toString' in {}; // true
Object.hasOwn({}, 'toString'); // false
28. How do you protect code from a third-party function that mutates inputs?
Answer
Answer: Pass an appropriate clone at the boundary, freeze values in development to detect mutation, and document ownership. structuredClone is suitable only for supported data.
29. How does a JavaScript program run?
Answer
Answer: The engine parses the source, creates execution contexts, compiles or interprets the code, and executes it on the call stack. Variables and functions are prepared during the creation phase, then statements run during the execution phase. In React Native, Hermes executes the JS bundle. Async operations are handled by native APIs and their callbacks return through the event loop.
30. How is this determined in JavaScript?
Answer
Answer: this is determined by the call site: method calls use the receiver, plain strict-mode calls use undefined, new uses the new instance, call/apply/bind set it explicitly, and arrows capture outer this.
31. JavaScript vs TypeScript?
Answer
Answer: TypeScript is JavaScript plus static types and compile-time tooling. It catches invalid props, API shapes, navigation params, and ref usage before runtime and improves refactoring. Types disappear at runtime, so API validation is still required. I use strict TypeScript, avoid broad any, model async states with unions, and generate types from schemas where possible.
32. Memoize a pure function (Medium)?
Example:Answer
Answer: Expected result: Repeated equivalent serialized arguments return the cached result.
Explanation: This is an interview baseline, not a universal production cache. JSON keys fail for cycles and some values; a robust version uses nested Maps/WeakMaps and may need eviction.
function memoize(fn) {
const cache = new Map();
return function (...args) {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
33. Object.assign({}, obj) vs { ...obj }?
Answer
Answer: Object.assign({}, source) and {...source} both create shallow copies of own enumerable properties. Spread is usually clearer for immutable updates, while Object.assign can write into an existing target. Neither clones nested values, so nested references remain shared.
34. Pure function and side effects?
Answer
Answer: A pure function returns the same output for the same inputs and does not mutate external state. Side effects include network calls, storage, logging, timers, and mutation. Redux reducers must be pure. I keep calculations pure and isolate effects in hooks, middleware, or service functions because pure code is easier to test and reason about.
35. Remove duplicate array values (Easy)?
Example:Answer
Answer: Expected result: [1, 2, 3]
Explanation: Set preserves insertion order and uses SameValueZero equality. For duplicate objects, I would need a stable key or a custom comparison.
function unique(values) {
return [...new Set(values)];
}
unique([1, 2, 2, 3, 1]);
36. Type coercion, null vs undefined, and typeof null?
Answer
Answer: undefined usually means missing or not assigned, while null is an intentional empty value. typeof null returns object because of a historical binary-tag bug preserved for compatibility; null is still a primitive. Loose equality coerces types, so I use strict equality except for deliberate patterns.
37. What does Object.create(proto) do?
Example:Answer
Answer: It creates a new object whose internal [[Prototype]] is proto. Object.create(null) creates a dictionary with no inherited properties.
const child = Object.create(parent);
38. What does an async function return?
Example:Answer
Answer: An async function always returns a Promise. A plain return value becomes a fulfilled Promise, while a thrown error becomes a rejected Promise.
async function test() {
return 10;
}
console.log(test()); // Promise fulfilled with 10
39. What happens if you call an async function without awaiting it?
Answer
Answer: The call immediately returns a Promise and following code continues. The work still runs, but ordering and rejection handling may be lost unless the Promise is awaited or consumed with then/catch.
40. What happens when a method is detached from its object?
Example:Answer
Answer: The receiver is lost, so a strict-mode call has this as undefined; accessing instance data fails or yields no expected value depending on the function body and environment.
const obj = {
name: 'React',
show() {
console.log(this?.name);
},
};
const fn = obj.show;
fn(); // undefined
41. What is a higher-order function?
Answer
Answer: A higher-order function accepts functions, returns a function, or both. map, filter, debounce, and middleware factories are common examples.
42. What is function composition, and how do compose and pipe differ?
Example:Answer
Answer: Composition feeds one function's output into the next. compose evaluates right-to-left, while pipe evaluates left-to-right.
const compose =
(...fs) =>
(x) =>
fs.reduceRight((v, f) => f(v), x);
const pipe =
(...fs) =>
(x) =>
fs.reduce((v, f) => f(v), x);
43. What is the difference between pure and impure functions?
Answer
Answer: A pure function returns the same result for the same inputs and has no observable side effects. An impure function may mutate state, perform I/O, read time/randomness, or depend on external mutable values.
🔴 Senior
44. What are JavaScript property descriptors?
Answer
Answer: A data-property descriptor defines value, writable, enumerable, and configurable; an accessor descriptor defines get and set. Object.defineProperty can control these attributes.
45. What happens when a JavaScript function is called?
Answer
Answer: A new execution context is pushed on the call stack. Its creation phase establishes lexical and variable environments, declarations, outer links, and this; its execution phase evaluates statements and assignments. It is popped when the call returns.
Advanced JavaScript
22 reviewed questions.
🟢 Beginner
1. What is event bubbling?
Answer
Answer: In the browser, bubbling sends an event from its target up through ancestors; capturing travels from the root toward the target. stopPropagation can halt propagation.
🟡 Intermediate
2. Currying and higher-order functions?
Example:Answer
Answer: A higher-order function accepts or returns functions. Currying transforms a multi-argument function like add(a,b) into add(a)(b), which enables reusable partial configuration. map, filter, debounce, middleware, and HOCs are higher-order patterns. I use currying when it improves composition, not just to make simple code clever.
const multiply = (a) => (b) => a * b;
const double = multiply(2);
double(5); // 10
3. Deep copy vs shallow copy?
Answer
Answer: A shallow copy creates a new outer container while preserving references to nested objects. A deep copy recursively copies supported nested values, but prototype, transfer, and serializability semantics depend on the mechanism. For React state I normally copy only the changed path; structuredClone is useful only when its supported-value and performance trade-offs fit.
4. Event delegation?
Answer
Answer: Event delegation attaches one handler to a common parent and uses the event target to handle many children. It works because browser events bubble and reduces listeners for dynamic lists. React Native has no DOM; it uses the responder and gesture systems, so I do not claim DOM event delegation applies directly to native views.
5. Explain this in regular functions, arrow functions, and methods?
Answer
Answer: In a method call, this is the object before the dot. In a plain strict-mode function it is undefined. call, apply, and bind set it explicitly. Arrow functions do not create their own this; they capture it lexically. That makes arrows useful for callbacks but unsuitable as constructors or methods that require a dynamic receiver.
6. How do call(), apply(), and bind() differ?
Example:Answer
Answer: call invokes immediately with positional arguments, apply invokes immediately with an argument array, and bind returns a new function with fixed this and optional preset arguments.
fn.call(obj, a, b);
fn.apply(obj, [a, b]);
const g = fn.bind(obj, a);
7. How do getters and setters work?
Example:Answer
Answer: Getters compute a value during property access, while setters intercept assignment. They can be declared in object literals or with defineProperty.
const o = {
get full() {
return this.a + ' ' + this.b;
},
set full(v) {
[this.a, this.b] = v.split(' ');
},
};
8. How does JavaScript garbage collection work?
Answer
Answer: Modern engines trace from roots such as globals and the stack, mark reachable objects, and reclaim unreachable ones; implementations also use generational optimizations.
9. How does the prototype chain work?
Answer
Answer: When an own property is absent, JavaScript follows [[Prototype]] links until it finds the property or reaches null.
10. Map and Set?
Answer
Answer: Map stores key-value pairs with keys of any type and preserves insertion order. Set stores unique values. They are better than plain objects for dynamic keys, reliable size, and iteration. WeakMap and WeakSet hold object keys weakly, so they are useful for metadata that should not prevent garbage collection.
11. Prototypes and inheritance?
Answer
Answer: Objects inherit through their internal prototype chain. A constructor's prototype becomes the prototype of objects created with new. Property lookup walks the object and then its prototypes. class is syntax over this mechanism. In React Native app code I prefer composition, but understanding prototypes explains methods, instanceof, and polyfills.
12. What is currying?
Example:Answer
Answer: Currying transforms a multi-argument function into a chain of one-argument functions, enabling specialization and partial reuse.
const add = (a) => (b) => a + b;
const add5 = add(5);
add5(3); // 8
🔴 Senior
13. Can bind change this on an already bound function?
Answer
Answer: No. Calling bind again creates another wrapper but does not replace the original bound this value.
14. How do WeakMap and WeakSet differ from Map and Set?
Answer
Answer: WeakMap and WeakSet hold object keys weakly, so entries do not keep otherwise unreachable keys alive and are not enumerable. Map and Set hold strong references and are iterable.
15. How do accessibility, privacy, and localization affect this design?
Answer
Answer: They shape primitives, focus and motion, data collection and retention, permissions, text expansion, RTL layout, formatting, and test matrices from the start.
16. How do lexical environment, scope chain, variable environment, and prototype chain differ?
Answer
Answer: A lexical environment stores identifier bindings and an outer link; the scope chain follows those links. VariableEnvironment is associated historically with var/function bindings. The prototype chain is separate and resolves object properties through [[Prototype]].
17. How does this behave on a low-end Android device with poor connectivity?
Answer
Answer: I test CPU, memory, storage, startup, rendering, retries, and offline UX on representative constrained hardware and networks rather than extrapolating from a flagship device.
18. How would another team safely extend or replace this component?
Answer
Answer: Provide a narrow versioned interface, ownership and ADRs, contract tests, observability, migration hooks, and an adapter boundary with no hidden global dependencies.
19. What are Proxy and Reflect used for?
Example:Answer
Answer: Proxy intercepts operations such as get, set, and apply for validation, defaults, or observability. Reflect exposes corresponding default operations and return conventions, making proxy traps easier to forward correctly.
const p = new Proxy(target, {
get(t, k, r) {
return Reflect.get(t, k, r);
},
});
20. What evidence would make you reverse this architecture decision?
Answer
Answer: I would define falsifiable success and failure thresholds before deciding, then reverse when production data, a benchmark, or a changed constraint crosses them.
21. What is garbage collection?
Answer
Answer: Garbage collection reclaims objects that are no longer reachable from application roots. Developers do not free JavaScript memory directly, but retained listeners, timers, closures, caches, or native references can keep objects reachable and cause memory growth.
22. What is the difference between prototype and proto?
Answer
Answer: A constructor function's prototype becomes the [[Prototype]] of instances made with new. proto is a legacy accessor for an object's [[Prototype]]; prefer Object.getPrototypeOf and Object.setPrototypeOf.
ES6+
10 reviewed questions.
🟢 Beginner
1. How do default parameters work?
Example:Answer
Answer: A default parameter is used when the corresponding argument is undefined, including an explicitly passed undefined; null does not trigger it.
function f(x = 10) {
return x;
}
2. What are template literals?
Example:Answer
Answer: Template literals use backticks, support ${expression} interpolation, and can span lines.
const s = `Hello ${name}`;
3. What is the difference between rest and spread syntax?
Example:Answer
Answer: Spread expands an iterable or object into elements or properties. Rest collects remaining parameters, elements, or properties. They share ... syntax but perform opposite roles.
const [a, ...rest] = [1, 2, 3];
const copy = { ...obj };
🟡 Intermediate
4. How do CommonJS and ES modules differ?
Answer
Answer: CommonJS uses require/module.exports and resolves at runtime. ES modules use declarative import/export, support live bindings, and are designed for static tooling and asynchronous loading.
5. How do Object.assign({}, obj) and object spread differ?
Example:Answer
Answer: Both copy enumerable own properties shallowly. Spread is concise and creates a new literal; Object.assign can mutate an existing target and merge multiple sources. Neither deep-clones nested values.
const a = { ...obj };
const b = Object.assign({}, obj);
6. Normal function, arrow function, and flying function?
Answer
Answer: JavaScript has no standard concept called a flying function. Interviewers usually mean an arrow function, callback, higher-order function, or immediately invoked function. A normal function has its own this and arguments and can be a constructor. An arrow function captures this lexically, has no arguments object, and cannot be used with new. I clarify the term before answering.
7. Scope, global variables, IIFE, and ES modules?
Answer
Answer: JavaScript has global, function, and block scope. Global variables live too long, create hidden dependencies, and can leak memory, so I prefer module scope or explicit state. An IIFE creates an immediate private scope, but ES modules now provide cleaner encapsulation. ES modules use import/export and are statically analyzable for tree shaking.
8. Spread vs rest, destructuring, optional chaining, and nullish coalescing?
Answer
Answer: Spread expands arrays or objects and is commonly used for immutable shallow copies. Rest collects remaining parameters or properties. Destructuring extracts values. Optional chaining safely returns undefined when a parent is nullish, and ?? supplies a default only for null or undefined, unlike || which also treats zero and empty string as missing.
9. What is optional chaining?
Answer
Answer: Spread expands arrays or objects and is commonly used for immutable shallow copies. Rest collects remaining parameters or properties. Destructuring extracts values. Optional chaining safely returns undefined when a parent is nullish, and ?? supplies a default only for null or undefined, unlike || which also treats zero and empty string as missing.
🔴 Senior
10. Why can ES modules be tree-shaken?
Answer
Answer: Top-level declarative imports and exports let bundlers determine the dependency graph and remove unused exports without executing modules.
Scope, Hoisting & Closures
7 reviewed questions.
🟢 Beginner
1. What is a closure? Give a React Native example?
Example:Answer
Answer: A closure is a function that remembers variables from its outer lexical scope even after that outer function has finished. For example, a counter function can keep a private count and return 1, then 2. In React Native, closures appear in useEffect, timers, and debounce. A common bug is a stale closure: setInterval with empty dependencies keeps logging the first count. I fix it with correct deps or a ref.
function makeCounter() {
let count = 0;
return () => ++count;
}
const c = makeCounter(); // 1, then 2
2. What is hoisting?
Example:Answer
Answer: Before execution, JavaScript registers declarations in their scope. var is initialized to undefined, function declarations are callable, and let/const remain uninitialized in the temporal dead zone. Code is not physically moved.
console.log(a); // undefined
var a = 10;
foo();
function foo() {}
3. What is the temporal dead zone (TDZ)?
Example:Answer
Answer: The TDZ runs from entry into a block until a let or const declaration is initialized. The binding exists but access before the declaration throws ReferenceError.
console.log(b); // ReferenceError
let b = 20;
🟡 Intermediate
4. What are closures and lexical scope?
Answer
Answer: Lexical scope means variable access depends on where a function is defined. A closure is a function that keeps access to that outer scope after the outer function returns. Closures power private counters, debounce, and event handlers, but a long-lived closure can retain large objects or capture stale React state.
5. What are scope and variable shadowing?
Answer
Answer: Global, function, and block scopes control visibility. Shadowing occurs when an inner declaration uses the same name and hides the outer binding within that inner scope.
6. What is lexical scope?
Answer
Answer: Lexical scope means variable access is determined by where functions are written, not where they are called. Nested functions can resolve names through their outer source scopes.
7. What is the Temporal Dead Zone and hoisting?
Answer
Answer: Hoisting means declarations are registered before execution. var is initialized with undefined, while let and const remain uninitialized in the Temporal Dead Zone until their declaration runs. Reading them in that period throws ReferenceError. Function declarations are fully available before their source line.
Event Loop & Async JavaScript
9 reviewed questions.
🟢 Beginner
1. What is the difference between synchronous and asynchronous code?
Answer
Answer: Synchronous code runs in order and blocks until each operation finishes. Asynchronous work starts now and completes later through callbacks, Promises, or async/await, allowing JavaScript to remain responsive while waiting for I/O.
🟡 Intermediate
2. Explain execution context, call stack, microtask queue, and task queue?
Example:Answer
Answer: An execution context stores the current function's variables, scope, this value, and code. The call stack tracks active contexts. Synchronous code runs first. After the stack is empty, all microtasks such as Promise callbacks run, then a macrotask such as setTimeout runs. This order explains why Promises execute before timers.
console.log('A');
setTimeout(() => console.log('B'), 0);
Promise.resolve().then(() => console.log('C'));
console.log('D');
// Output: A D C B
3. How do you cancel asynchronous work when a component unmounts?
Example:Answer
Answer: Abort cancellable requests and clear timers, listeners, and subscriptions in the effect cleanup. For APIs without cancellation, ignore results after cleanup.
useEffect(() => {
const c = new AbortController();
fetch(url, { signal: c.signal });
return () => c.abort();
}, [url]);
4. How does the JavaScript event loop work?
Answer
Answer: JavaScript runs synchronous work on one call stack. After the stack empties, it drains queued microtasks such as Promise callbacks before taking the next macrotask such as a timer. Long synchronous work blocks progress.
5. Implement setInterval using setTimeout (Hard)?
Example:Answer
Answer: Expected result: Repeatedly invokes callback and returns a cancellation function.
Explanation: Recursive setTimeout schedules after callback completion and avoids overlapping callbacks. Timers are not exact; backgrounding and a busy JS thread can delay them.
function createInterval(callback, delay) {
let timer = null;
let active = true;
function tick() {
timer = setTimeout(() => {
if (!active) return;
callback();
tick();
}, delay);
}
tick();
return () => {
active = false;
clearTimeout(timer);
};
}
6. Retry an asynchronous operation (Medium/Hard)?
Example:Answer
Answer: Expected result: Returns the first successful result or throws the final error.
Explanation: I clarify whether attempts includes the first call. In production I add exponential backoff, jitter, cancellation, retryable-error filtering and idempotency checks.
async function retry(operation, attempts, delay = 0) {
let lastError;
for (let i = 0; i < attempts; i++) {
try {
return await operation();
} catch (error) {
lastError = error;
if (i < attempts - 1 && delay) {
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}
throw lastError;
}
7. What causes 'Maximum call stack size exceeded'?
Example:Answer
Answer: Infinite recursion or excessively deep nested calls exhaust the call stack because each unfinished call retains a stack frame.
function f() {
f();
} // RangeError
8. Why can Promise and setTimeout logs appear in an unexpected order?
Answer
Answer: Synchronous code runs first, then queued microtasks, then timer macrotasks. Nested scheduling adds new work to the relevant queue, so reason in enqueue order rather than timer delay alone.
9. setTimeout vs setInterval, and how do you clean them?
Answer
Answer: setTimeout schedules one callback after at least the requested delay; setInterval repeats approximately at an interval. Neither guarantees exact timing because callbacks wait for the call stack. In React Native I store the timer id in a ref and call clearTimeout or clearInterval in useEffect cleanup to avoid leaks and callbacks after unmount.
Promises & Async/Await
15 reviewed questions.
🟢 Beginner
1. How do you create a Promise that resolves after 10 seconds?
Example:Answer
Answer: I return a new Promise and resolve it inside setTimeout. The timeout places a callback in the task queue after at least ten seconds; it may run later if the call stack is busy. In production I also expose cancellation through AbortController when the operation is real I/O.
const delay = (ms) =>
new Promise((resolve) => setTimeout(resolve, ms));
await delay(10_000);
2. What is a Promise, and what are its states?
Answer
Answer: A Promise represents a future value. It begins pending and settles once as fulfilled with a value or rejected with a reason; a settled Promise cannot change state.
🟡 Intermediate
3. Callback, Promise, async/await, and callback hell?
Answer
Answer: A callback is a function invoked later. Deeply nested callbacks create callback hell, making ordering and errors difficult. A Promise represents a future value and supports then, catch, and finally. async/await is syntax over Promises that makes control flow readable. I use try/catch with await and Promise.all when independent operations can run in parallel.
4. How do callbacks, Promises, and async/await differ?
Answer
Answer: A callback is a function invoked later. A Promise models a future result with then, catch, and finally. async/await is syntax built on Promises that makes asynchronous control flow easier to read.
5. How do sequential and parallel await patterns differ?
Example:Answer
Answer: await api1(); await api2(); runs sequentially. Starting both inside Promise.all runs independent operations concurrently and waits for both.
await api1();
await api2();
await Promise.all([api1(), api2()]);
6. How do you handle errors in async/await?
Answer
Answer: I catch errors at the boundary that can add context or recover, not around every await. I normalize transport, domain, cancellation, and programmer errors, present an actionable user state, and retry only transient idempotent operations with bounded backoff and jitter. Errors that cannot be handled are rethrown or reported with useful context.
7. Implement Promise.all (Hard)?
Example:Answer
Answer: Expected result: Resolves ordered results when all fulfill; rejects on the first rejection.
Explanation: Results preserve input order, not completion order. Promise.resolve supports plain values and thenables. The empty iterable resolves to an empty array.
function promiseAll(values) {
return new Promise((resolve, reject) => {
const items = Array.from(values);
if (items.length === 0) return resolve([]);
const results = new Array(items.length);
let completed = 0;
items.forEach((item, index) => {
Promise.resolve(item).then((value) => {
results[index] = value;
completed++;
if (completed === items.length) resolve(results);
}, reject);
});
});
}
8. Implement Promise.allSettled (Hard)?
Example:Answer
Answer: Expected result: Always fulfills with one status object per input.
Explanation: I convert each rejection into a fulfilled status object, so the outer Promise.all cannot fail because of an input rejection.
function allSettled(values) {
return Promise.all(
Array.from(values, (item) =>
Promise.resolve(item).then(
(value) => ({ status: 'fulfilled', value }),
(reason) => ({ status: 'rejected', reason }),
),
),
);
}
9. Implement a concurrency-limited promise queue?
Example:Answer
Answer: I keep a shared next index and start only limit worker loops. Each worker takes the next task, awaits it, stores the result at the original index, then takes another task. Promise.all waits for the workers. This limits pressure on APIs while retaining parallelism and can be extended with retries and allSettled behavior.
async function pool(tasks, limit) {
const results = new Array(tasks.length);
let next = 0;
async function worker() {
while (next < tasks.length) {
const i = next++;
results[i] = await tasks[i]();
}
}
await Promise.all(
Array.from({ length: Math.min(limit, tasks.length) }, worker),
);
return results;
}
10. One rejects in Promise.all?
Answer
Answer: Promise.all rejects as soon as any input rejects, so the combined Promise is not fulfilled. Other operations are not automatically cancelled and may continue; use allSettled when every outcome is required and explicit cancellation when unfinished work should stop.
11. Promise.all, allSettled, race, and any?
Answer
Answer: Promise.all waits for all and rejects on the first failure. allSettled waits for every result and reports each status. race settles with the first settled promise, while any fulfills with the first success and rejects only if all fail. I use all for required parallel calls and allSettled when partial success is acceptable.
12. Retry a failed Promise?
Answer
Answer: Wrap the operation in a function so each attempt creates a new Promise. Retry only transient failures, cap the attempt count, preserve the final error, and do not automatically retry non-idempotent writes unless the backend supports idempotency.
13. What happens if you don't await an async function?
Answer
Answer: Calling an async function without await starts it and immediately returns a Promise. The caller continues, so ordering assumptions may break, and a rejection can become unhandled unless the Promise is returned, awaited, or given an explicit catch handler.
14. What happens when one Promise in Promise.all rejects?
Answer
Answer: Promise.all rejects with that reason as soon as the rejection is observed. The other operations are not automatically cancelled and may continue running.
15. Why might a Promise chain stop unexpectedly?
Answer
Answer: Likely causes include an unhandled rejection, a missing return from then, an error swallowed in catch, or a forgotten await. Trace settlement and ensure every branch returns or throws deliberately.
React Fundamentals
15 reviewed questions.
🟢 Beginner
1. Props vs state?
Answer
Answer: Props are inputs passed from parent to child and should be treated as read-only. State is data owned by the component that can change over time and triggers a re-render when updated. If a sibling needs the same data, I lift state up to a common parent and pass it down as props.
2. What is the Virtual DOM?
Answer
Answer: It is the conceptual in-memory description of UI elements that React compares before committing host updates; Fiber is the implementation that manages the work.
🟡 Intermediate
3. Controlled vs uncontrolled components?
Answer
Answer: A controlled input receives its value from React state and reports changes back, which makes validation and reset predictable. An uncontrolled input keeps its own value and is read through a ref. I prefer controlled React Native forms for most cases, but a form library may use refs internally to reduce re-renders in very large forms.
4. How did ref handling change in React 19?
Example:Answer
Answer: Function components can receive ref as a prop in React 19, reducing the need for forwardRef in new code. React 19 also supports cleanup functions returned from ref callbacks. Existing forwardRef code continues to work, so teams can migrate gradually rather than rewriting every component. In React Native, availability follows the React version bundled by the chosen React Native release, so I verify that toolchain before using the API.
<TextInput ref={ref} {...props} />;
}
5. How do you manage a complex form with 15+ fields?
Answer
Answer: I avoid one global Context update per keystroke. I use React Hook Form or a focused custom form hook with field-level subscriptions, schema validation such as Zod/Yup, and separate server errors. Redux is unnecessary unless form drafts must be shared across screens; Zustand can fit multi-step drafts. The main goal is predictable validation without re-rendering every field.
6. PureComponent, pure function, and React.memo?
Answer
Answer: A pure function has no side effects. React.PureComponent is a class optimization that shallowly compares props and state. React.memo is the function-component equivalent for props. Both fail to detect deep mutation and can be defeated by new object or function props, so I preserve immutability and stabilize only measured hot paths.
7. Real DOM vs Virtual DOM in React Native?
Answer
Answer: The real DOM is the browser's mutable document tree. The Virtual DOM is an in-memory description React reconciles before updating the host platform. React Native does not have a browser DOM; its host nodes are native views. Fiber still reconciles React elements, then Fabric or the legacy renderer applies changes to UIView and Android View objects.
8. What is reconciliation?
Answer
Answer: Reconciliation is React's process of comparing element trees and scheduling the minimum host updates needed to reflect new props and state.
9. What is the React 19 context provider shorthand?
Example:Answer
Answer: React 19 allows a context object itself to be rendered as the provider instead of requiring Context.Provider. The value and update behavior are unchanged; this is a syntax simplification. Provider values should still be stable when avoidable re-renders matter. In React Native, availability follows the React version bundled by the chosen React Native release, so I verify that toolchain before using the API.
<ThemeContext value={theme}>
<App />
</ThemeContext>;
10. Why should React state not be mutated directly?
Example:Answer
Answer: React uses identity and prior state to schedule and optimize rendering. In-place mutation can preserve the same reference, skip expected updates, and corrupt previous snapshots.
setItems((prev) => [...prev, item]);
🔴 Senior
11. How does useActionState work in React 19?
Example:Answer
Answer: useActionState connects an Action to its latest returned state and pending status. The Action receives the previous state followed by the submitted payload, which makes validation and server responses explicit. It is useful when submission state belongs to the mutation rather than to several independent useState calls. In React Native, availability follows the React version bundled by the chosen React Native release, so I verify that toolchain before using the API.
const [result, save, isPending] = useActionState(saveProfile, {
error: null,
});
// Call save(payload) from the submit interaction.
12. How should errors from React 19 Actions be handled?
Example:Answer
Answer: Expected validation failures should be returned as typed Action state so the UI can render them next to the relevant input. Unexpected failures should be logged and allowed to reach an error boundary or a controlled mutation error state. Cancellation, duplicate submission, retry, and idempotency still need application-level policies. In React Native, availability follows the React version bundled by the chosen React Native release, so I verify that toolchain before using the API.
Return {fieldErrors, message} for expected failures; report unexpected exceptions with the operation name, app version, and correlation ID.
Continue the series
Open the Complete React Native Interview Handbook 2026 series page on Dev.to for the next part.











