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
@@ -227,3 +227,332 @@ If you try to use **{ref.current}** in the render method, the number won’t be
227
227
---
228
228
229
229
**[⬆ Back to Top](#table-of-contents)**
230
+
231
+
#### 6. What is the output in the console after mounting and unmounting the component?
232
+
233
+
```javascript
234
+
import { useEffect, useState } from'react';
235
+
236
+
exportdefaultfunctionTimer() {
237
+
const [count, setCount] =useState(0);
238
+
239
+
useEffect(() => {
240
+
console.log('Effect ran');
241
+
consttimer=setInterval(() => {
242
+
setCount(c=> c +1);
243
+
}, 1000);
244
+
245
+
console.log('Cleanup registered');
246
+
return () => {
247
+
console.log('Cleanup executed');
248
+
clearInterval(timer);
249
+
};
250
+
}, []);
251
+
252
+
return<div>Count: {count}</div>;
253
+
}
254
+
```
255
+
256
+
- 1: "Effect ran", "Cleanup registered", "Cleanup executed" (on mount), "Cleanup executed" (on unmount)
257
+
- 2: "Effect ran", "Cleanup registered" (on mount), "Cleanup executed" (on unmount)
258
+
- 3: "Effect ran" (on mount), "Cleanup executed" (on unmount)
259
+
- 4: "Effect ran", "Cleanup registered", "Cleanup executed" (on mount and unmount)
260
+
261
+
<details><summary><b>Answer</b></summary>
262
+
<p>
263
+
264
+
##### Answer: 2
265
+
266
+
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.
267
+
268
+
The cleanup function executes in two scenarios:
269
+
1. **Before re-running the effect** (if dependencies change)
270
+
2. **When the component unmounts**
271
+
272
+
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.
273
+
274
+
This pattern is crucial for preventing memory leaks when using timers, subscriptions, or event listeners in React components.
275
+
276
+
</p>
277
+
</details>
278
+
279
+
---
280
+
281
+
**[⬆ Back to Top](#table-of-contents)**
282
+
283
+
#### 7. What will be the output after clicking the button?
284
+
285
+
```javascript
286
+
import { useState } from'react';
287
+
288
+
exportdefaultfunctionApp() {
289
+
const [items, setItems] =useState([1, 2, 3]);
290
+
291
+
functionhandleClick() {
292
+
items.push(4);
293
+
setItems(items);
294
+
}
295
+
296
+
return (
297
+
<>
298
+
<div>Items: {items.join(', ')}</div>
299
+
<button onClick={handleClick}>Add Item</button>
300
+
</>
301
+
);
302
+
}
303
+
```
304
+
305
+
- 1: Items: 1, 2, 3, 4
306
+
- 2: Items: 1, 2, 3
307
+
- 3: Error: Cannot mutate state directly
308
+
- 4: Items: 1, 2, 3, 4, 4 (duplicates on each click)
309
+
310
+
<details><summary><b>Answer</b></summary>
311
+
<p>
312
+
313
+
##### Answer: 2
314
+
315
+
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.
316
+
317
+
To properly update an array in state, you should create a new array:
318
+
```javascript
319
+
setItems([...items, 4]); // or
320
+
setItems(items.concat(4));
321
+
```
322
+
323
+
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.
324
+
325
+
</p>
326
+
</details>
327
+
328
+
---
329
+
330
+
**[⬆ Back to Top](#table-of-contents)**
331
+
332
+
#### 8. What is the output after the component mounts?
333
+
334
+
```javascript
335
+
import { useState, useEffect } from'react';
336
+
337
+
exportdefaultfunctionCounter() {
338
+
const [count, setCount] =useState(0);
339
+
340
+
useEffect(() => {
341
+
setCount(1);
342
+
});
343
+
344
+
useEffect(() => {
345
+
setCount(2);
346
+
}, []);
347
+
348
+
console.log('Rendered with count:', count);
349
+
350
+
return<div>Count: {count}</div>;
351
+
}
352
+
```
353
+
354
+
- 1: "Rendered with count: 0", "Rendered with count: 2"
355
+
- 2: "Rendered with count: 0", "Rendered with count: 1", "Rendered with count: 2"
356
+
- 3: Infinite loop / Maximum update depth exceeded error
357
+
- 4: "Rendered with count: 0", "Rendered with count: 2", "Rendered with count: 1"
358
+
359
+
<details><summary><b>Answer</b></summary>
360
+
<p>
361
+
362
+
##### Answer: 3
363
+
364
+
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:
365
+
366
+
1. Initial render with `count:0`
367
+
2. After render, both effects run (first sets count to 1, second sets count to 2)
368
+
3. State update triggers re-render with `count:2`
369
+
4. After render, the first effect runs again (no dependencies), setting count to 1
370
+
5. This triggers another re-render, and the cycle continues infinitely
371
+
372
+
React will detect this and throw an error: **"Maximum update depth exceeded"**.
373
+
374
+
The fix is to add a dependency array to the first useEffect:
375
+
```javascript
376
+
useEffect(() => {
377
+
setCount(1);
378
+
}, []); // Add empty dependency array
379
+
```
380
+
381
+
</p>
382
+
</details>
383
+
384
+
---
385
+
386
+
**[⬆ Back to Top](#table-of-contents)**
387
+
388
+
#### 9. What will be displayed on the screen?
389
+
390
+
```javascript
391
+
import { useMemo } from'react';
392
+
393
+
exportdefaultfunctionApp() {
394
+
constexpensiveCalculation=useMemo(() => {
395
+
console.log('Calculating...');
396
+
return100+200;
397
+
});
398
+
399
+
return<div>Result: {expensiveCalculation}</div>;
400
+
}
401
+
```
402
+
403
+
- 1: Result: 300
404
+
- 2: Result: function() { ... }
405
+
- 3: Result: undefined
406
+
- 4: Error: useMemo requires a dependency array
407
+
408
+
<details><summary><b>Answer</b></summary>
409
+
<p>
410
+
411
+
##### Answer: 4
412
+
413
+
The `useMemo` hook **requires** a dependency array as the second argument. Without it, React will throw an error during development:
414
+
415
+
```
416
+
Error: useMemo requires a dependency array as the second argument
417
+
```
418
+
419
+
The correct usage is:
420
+
```javascript
421
+
constexpensiveCalculation=useMemo(() => {
422
+
console.log('Calculating...');
423
+
return100+200;
424
+
}, []); // Dependency array is required
425
+
```
426
+
427
+
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.
428
+
429
+
</p>
430
+
</details>
431
+
432
+
---
433
+
434
+
**[⬆ Back to Top](#table-of-contents)**
435
+
436
+
#### 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.
472
+
473
+
Even though `person.age` is being incremented internally, the UI shows the initial value (30) because React never re-renders the component.
474
+
475
+
The correct approach is to create a new object:
476
+
```javascript
477
+
functionhandleClick() {
478
+
setPerson({
479
+
...person,
480
+
age:person.age+1
481
+
});
482
+
}
483
+
```
484
+
485
+
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