You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: coding-exercise/README.md
+329Lines changed: 329 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -228,3 +228,332 @@ If you try to use **{ref.current}** in the render method, the number won’t be
228
228
---
229
229
230
230
**[⬆ Back to Top](#table-of-contents)**
231
+
232
+
#### 6. What is the output in the console after mounting and unmounting the component?
233
+
234
+
```javascript
235
+
import { useEffect, useState } from'react';
236
+
237
+
exportdefaultfunctionTimer() {
238
+
const [count, setCount] =useState(0);
239
+
240
+
useEffect(() => {
241
+
console.log('Effect ran');
242
+
consttimer=setInterval(() => {
243
+
setCount(c=> c +1);
244
+
}, 1000);
245
+
246
+
console.log('Cleanup registered');
247
+
return () => {
248
+
console.log('Cleanup executed');
249
+
clearInterval(timer);
250
+
};
251
+
}, []);
252
+
253
+
return<div>Count: {count}</div>;
254
+
}
255
+
```
256
+
257
+
- 1: "Effect ran", "Cleanup registered", "Cleanup executed" (on mount), "Cleanup executed" (on unmount)
258
+
- 2: "Effect ran", "Cleanup registered" (on mount), "Cleanup executed" (on unmount)
259
+
- 3: "Effect ran" (on mount), "Cleanup executed" (on unmount)
260
+
- 4: "Effect ran", "Cleanup registered", "Cleanup executed" (on mount and unmount)
261
+
262
+
<details><summary><b>Answer</b></summary>
263
+
<p>
264
+
265
+
##### Answer: 2
266
+
267
+
When a component mounts, React runs the effect function completely, which logs both "Effect ran" and "Cleanup registered". The cleanup function (returned from useEffect) is **not** executed during mount - it's only registered at this point.
268
+
269
+
The cleanup function executes in two scenarios:
270
+
1. **Before re-running the effect** (if dependencies change)
271
+
2. **When the component unmounts**
272
+
273
+
Since the dependency array is empty `[]`, the effect only runs once on mount and never re-runs. Therefore, the cleanup function will only execute when the component unmounts, logging "Cleanup executed" and clearing the interval timer.
274
+
275
+
This pattern is crucial for preventing memory leaks when using timers, subscriptions, or event listeners in React components.
276
+
277
+
</p>
278
+
</details>
279
+
280
+
---
281
+
282
+
**[⬆ Back to Top](#table-of-contents)**
283
+
284
+
#### 7. What will be the output after clicking the button?
285
+
286
+
```javascript
287
+
import { useState } from'react';
288
+
289
+
exportdefaultfunctionApp() {
290
+
const [items, setItems] =useState([1, 2, 3]);
291
+
292
+
functionhandleClick() {
293
+
items.push(4);
294
+
setItems(items);
295
+
}
296
+
297
+
return (
298
+
<>
299
+
<div>Items: {items.join(', ')}</div>
300
+
<button onClick={handleClick}>Add Item</button>
301
+
</>
302
+
);
303
+
}
304
+
```
305
+
306
+
- 1: Items: 1, 2, 3, 4
307
+
- 2: Items: 1, 2, 3
308
+
- 3: Error: Cannot mutate state directly
309
+
- 4: Items: 1, 2, 3, 4, 4 (duplicates on each click)
310
+
311
+
<details><summary><b>Answer</b></summary>
312
+
<p>
313
+
314
+
##### Answer: 2
315
+
316
+
React uses `Object.is()` comparison to detect state changes. When you mutate the array directly using `items.push(4)` and then pass the same array reference to `setItems(items)`, React sees it as the same object (same reference) and doesn't trigger a re-render.
317
+
318
+
To properly update an array in state, you should create a new array:
319
+
```javascript
320
+
setItems([...items, 4]); // or
321
+
setItems(items.concat(4));
322
+
```
323
+
324
+
This is a common mistake that leads to bugs where the UI doesn't update even though the underlying data has changed. Always treat state as immutable in React.
325
+
326
+
</p>
327
+
</details>
328
+
329
+
---
330
+
331
+
**[⬆ Back to Top](#table-of-contents)**
332
+
333
+
#### 8. What is the output after the component mounts?
334
+
335
+
```javascript
336
+
import { useState, useEffect } from'react';
337
+
338
+
exportdefaultfunctionCounter() {
339
+
const [count, setCount] =useState(0);
340
+
341
+
useEffect(() => {
342
+
setCount(1);
343
+
});
344
+
345
+
useEffect(() => {
346
+
setCount(2);
347
+
}, []);
348
+
349
+
console.log('Rendered with count:', count);
350
+
351
+
return<div>Count: {count}</div>;
352
+
}
353
+
```
354
+
355
+
- 1: "Rendered with count: 0", "Rendered with count: 2"
356
+
- 2: "Rendered with count: 0", "Rendered with count: 1", "Rendered with count: 2"
357
+
- 3: Infinite loop / Maximum update depth exceeded error
358
+
- 4: "Rendered with count: 0", "Rendered with count: 2", "Rendered with count: 1"
359
+
360
+
<details><summary><b>Answer</b></summary>
361
+
<p>
362
+
363
+
##### Answer: 3
364
+
365
+
This code creates an **infinite loop** because the first `useEffect` has no dependency array, which means it runs after **every render**. Here's what happens:
366
+
367
+
1. Initial render with `count:0`
368
+
2. After render, both effects run (first sets count to 1, second sets count to 2)
369
+
3. State update triggers re-render with `count:2`
370
+
4. After render, the first effect runs again (no dependencies), setting count to 1
371
+
5. This triggers another re-render, and the cycle continues infinitely
372
+
373
+
React will detect this and throw an error: **"Maximum update depth exceeded"**.
374
+
375
+
The fix is to add a dependency array to the first useEffect:
376
+
```javascript
377
+
useEffect(() => {
378
+
setCount(1);
379
+
}, []); // Add empty dependency array
380
+
```
381
+
382
+
</p>
383
+
</details>
384
+
385
+
---
386
+
387
+
**[⬆ Back to Top](#table-of-contents)**
388
+
389
+
#### 9. What will be displayed on the screen?
390
+
391
+
```javascript
392
+
import { useMemo } from'react';
393
+
394
+
exportdefaultfunctionApp() {
395
+
constexpensiveCalculation=useMemo(() => {
396
+
console.log('Calculating...');
397
+
return100+200;
398
+
});
399
+
400
+
return<div>Result: {expensiveCalculation}</div>;
401
+
}
402
+
```
403
+
404
+
- 1: Result: 300
405
+
- 2: Result: function() { ... }
406
+
- 3: Result: undefined
407
+
- 4: Error: useMemo requires a dependency array
408
+
409
+
<details><summary><b>Answer</b></summary>
410
+
<p>
411
+
412
+
##### Answer: 4
413
+
414
+
The `useMemo` hook **requires** a dependency array as the second argument. Without it, React will throw an error during development:
415
+
416
+
```
417
+
Error: useMemo requires a dependency array as the second argument
418
+
```
419
+
420
+
The correct usage is:
421
+
```javascript
422
+
constexpensiveCalculation=useMemo(() => {
423
+
console.log('Calculating...');
424
+
return100+200;
425
+
}, []); // Dependency array is required
426
+
```
427
+
428
+
With an empty dependency array `[]`, the calculation runs once during the initial render and the memoized value (300) is reused on subsequent renders. If you include dependencies, the calculation re-runs whenever those dependencies change.
429
+
430
+
</p>
431
+
</details>
432
+
433
+
---
434
+
435
+
**[⬆ Back to Top](#table-of-contents)**
436
+
437
+
#### 10. What is the output after clicking the button twice?
Similar to the array mutation issue, directly mutating an object's property and then passing the same object reference to the state setter doesn't trigger a re-render. React uses `Object.is()` to compare the old and new state values. Since `person` is still the same object reference, React doesn't detect any change.
473
+
474
+
Even though `person.age` is being incremented internally, the UI shows the initial value (30) because React never re-renders the component.
475
+
476
+
The correct approach is to create a new object:
477
+
```javascript
478
+
functionhandleClick() {
479
+
setPerson({
480
+
...person,
481
+
age:person.age+1
482
+
});
483
+
}
484
+
```
485
+
486
+
This creates a new object with a new reference, which React recognizes as a state change and triggers a re-render. This is a fundamental principle in React: **always treat state as immutable**.
0 commit comments