@shaykec/bridge 0.4.25 → 0.4.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/journeys/ai-engineer.yaml +34 -0
- package/journeys/backend-developer.yaml +36 -0
- package/journeys/business-analyst.yaml +37 -0
- package/journeys/devops-engineer.yaml +37 -0
- package/journeys/engineering-manager.yaml +44 -0
- package/journeys/frontend-developer.yaml +41 -0
- package/journeys/fullstack-developer.yaml +49 -0
- package/journeys/mobile-developer.yaml +42 -0
- package/journeys/product-manager.yaml +35 -0
- package/journeys/qa-engineer.yaml +37 -0
- package/journeys/ux-designer.yaml +43 -0
- package/modules/README.md +52 -0
- package/modules/accessibility-fundamentals/content.md +126 -0
- package/modules/accessibility-fundamentals/exercises.md +88 -0
- package/modules/accessibility-fundamentals/module.yaml +43 -0
- package/modules/accessibility-fundamentals/quick-ref.md +71 -0
- package/modules/accessibility-fundamentals/quiz.md +100 -0
- package/modules/accessibility-fundamentals/resources.md +29 -0
- package/modules/accessibility-fundamentals/walkthrough.md +80 -0
- package/modules/adr-writing/content.md +121 -0
- package/modules/adr-writing/exercises.md +81 -0
- package/modules/adr-writing/module.yaml +41 -0
- package/modules/adr-writing/quick-ref.md +57 -0
- package/modules/adr-writing/quiz.md +73 -0
- package/modules/adr-writing/resources.md +29 -0
- package/modules/adr-writing/walkthrough.md +64 -0
- package/modules/ai-agents/content.md +120 -0
- package/modules/ai-agents/exercises.md +82 -0
- package/modules/ai-agents/module.yaml +42 -0
- package/modules/ai-agents/quick-ref.md +60 -0
- package/modules/ai-agents/quiz.md +103 -0
- package/modules/ai-agents/resources.md +30 -0
- package/modules/ai-agents/walkthrough.md +85 -0
- package/modules/ai-assisted-research/content.md +136 -0
- package/modules/ai-assisted-research/exercises.md +80 -0
- package/modules/ai-assisted-research/module.yaml +42 -0
- package/modules/ai-assisted-research/quick-ref.md +67 -0
- package/modules/ai-assisted-research/quiz.md +73 -0
- package/modules/ai-assisted-research/resources.md +33 -0
- package/modules/ai-assisted-research/walkthrough.md +85 -0
- package/modules/ai-pair-programming/content.md +105 -0
- package/modules/ai-pair-programming/exercises.md +98 -0
- package/modules/ai-pair-programming/module.yaml +39 -0
- package/modules/ai-pair-programming/quick-ref.md +58 -0
- package/modules/ai-pair-programming/quiz.md +73 -0
- package/modules/ai-pair-programming/resources.md +34 -0
- package/modules/ai-pair-programming/walkthrough.md +117 -0
- package/modules/ai-test-generation/content.md +125 -0
- package/modules/ai-test-generation/exercises.md +98 -0
- package/modules/ai-test-generation/module.yaml +39 -0
- package/modules/ai-test-generation/quick-ref.md +65 -0
- package/modules/ai-test-generation/quiz.md +74 -0
- package/modules/ai-test-generation/resources.md +41 -0
- package/modules/ai-test-generation/walkthrough.md +100 -0
- package/modules/api-design/content.md +189 -0
- package/modules/api-design/exercises.md +84 -0
- package/modules/api-design/game.yaml +113 -0
- package/modules/api-design/module.yaml +45 -0
- package/modules/api-design/quick-ref.md +73 -0
- package/modules/api-design/quiz.md +100 -0
- package/modules/api-design/resources.md +55 -0
- package/modules/api-design/walkthrough.md +88 -0
- package/modules/clean-code/content.md +136 -0
- package/modules/clean-code/exercises.md +137 -0
- package/modules/clean-code/game.yaml +172 -0
- package/modules/clean-code/module.yaml +44 -0
- package/modules/clean-code/quick-ref.md +44 -0
- package/modules/clean-code/quiz.md +105 -0
- package/modules/clean-code/resources.md +40 -0
- package/modules/clean-code/walkthrough.md +78 -0
- package/modules/clean-code/workshop.yaml +149 -0
- package/modules/code-review/content.md +130 -0
- package/modules/code-review/exercises.md +95 -0
- package/modules/code-review/game.yaml +83 -0
- package/modules/code-review/module.yaml +42 -0
- package/modules/code-review/quick-ref.md +77 -0
- package/modules/code-review/quiz.md +105 -0
- package/modules/code-review/resources.md +40 -0
- package/modules/code-review/walkthrough.md +106 -0
- package/modules/daily-workflow/content.md +81 -0
- package/modules/daily-workflow/exercises.md +50 -0
- package/modules/daily-workflow/module.yaml +33 -0
- package/modules/daily-workflow/quick-ref.md +37 -0
- package/modules/daily-workflow/quiz.md +65 -0
- package/modules/daily-workflow/resources.md +38 -0
- package/modules/daily-workflow/walkthrough.md +83 -0
- package/modules/debugging-systematically/content.md +139 -0
- package/modules/debugging-systematically/exercises.md +91 -0
- package/modules/debugging-systematically/module.yaml +46 -0
- package/modules/debugging-systematically/quick-ref.md +59 -0
- package/modules/debugging-systematically/quiz.md +105 -0
- package/modules/debugging-systematically/resources.md +42 -0
- package/modules/debugging-systematically/walkthrough.md +84 -0
- package/modules/debugging-systematically/workshop.yaml +127 -0
- package/modules/demo-test/content.md +68 -0
- package/modules/demo-test/exercises.md +28 -0
- package/modules/demo-test/game.yaml +171 -0
- package/modules/demo-test/module.yaml +41 -0
- package/modules/demo-test/quick-ref.md +54 -0
- package/modules/demo-test/quiz.md +74 -0
- package/modules/demo-test/resources.md +21 -0
- package/modules/demo-test/walkthrough.md +122 -0
- package/modules/demo-test/workshop.yaml +31 -0
- package/modules/design-critique/content.md +93 -0
- package/modules/design-critique/exercises.md +71 -0
- package/modules/design-critique/module.yaml +41 -0
- package/modules/design-critique/quick-ref.md +63 -0
- package/modules/design-critique/quiz.md +73 -0
- package/modules/design-critique/resources.md +27 -0
- package/modules/design-critique/walkthrough.md +68 -0
- package/modules/design-patterns/content.md +335 -0
- package/modules/design-patterns/exercises.md +82 -0
- package/modules/design-patterns/game.yaml +55 -0
- package/modules/design-patterns/module.yaml +45 -0
- package/modules/design-patterns/quick-ref.md +44 -0
- package/modules/design-patterns/quiz.md +101 -0
- package/modules/design-patterns/resources.md +40 -0
- package/modules/design-patterns/walkthrough.md +64 -0
- package/modules/exploratory-testing/content.md +133 -0
- package/modules/exploratory-testing/exercises.md +88 -0
- package/modules/exploratory-testing/module.yaml +41 -0
- package/modules/exploratory-testing/quick-ref.md +68 -0
- package/modules/exploratory-testing/quiz.md +75 -0
- package/modules/exploratory-testing/resources.md +39 -0
- package/modules/exploratory-testing/walkthrough.md +87 -0
- package/modules/git/content.md +128 -0
- package/modules/git/exercises.md +53 -0
- package/modules/git/game.yaml +190 -0
- package/modules/git/module.yaml +44 -0
- package/modules/git/quick-ref.md +67 -0
- package/modules/git/quiz.md +89 -0
- package/modules/git/resources.md +49 -0
- package/modules/git/walkthrough.md +92 -0
- package/modules/git/workshop.yaml +145 -0
- package/modules/hiring-interviews/content.md +130 -0
- package/modules/hiring-interviews/exercises.md +88 -0
- package/modules/hiring-interviews/module.yaml +41 -0
- package/modules/hiring-interviews/quick-ref.md +68 -0
- package/modules/hiring-interviews/quiz.md +73 -0
- package/modules/hiring-interviews/resources.md +36 -0
- package/modules/hiring-interviews/walkthrough.md +75 -0
- package/modules/hooks/content.md +97 -0
- package/modules/hooks/exercises.md +69 -0
- package/modules/hooks/module.yaml +39 -0
- package/modules/hooks/quick-ref.md +93 -0
- package/modules/hooks/quiz.md +81 -0
- package/modules/hooks/resources.md +34 -0
- package/modules/hooks/walkthrough.md +105 -0
- package/modules/hooks/workshop.yaml +64 -0
- package/modules/incident-response/content.md +124 -0
- package/modules/incident-response/exercises.md +82 -0
- package/modules/incident-response/game.yaml +132 -0
- package/modules/incident-response/module.yaml +45 -0
- package/modules/incident-response/quick-ref.md +53 -0
- package/modules/incident-response/quiz.md +103 -0
- package/modules/incident-response/resources.md +40 -0
- package/modules/incident-response/walkthrough.md +82 -0
- package/modules/llm-fundamentals/content.md +114 -0
- package/modules/llm-fundamentals/exercises.md +83 -0
- package/modules/llm-fundamentals/module.yaml +42 -0
- package/modules/llm-fundamentals/quick-ref.md +64 -0
- package/modules/llm-fundamentals/quiz.md +103 -0
- package/modules/llm-fundamentals/resources.md +30 -0
- package/modules/llm-fundamentals/walkthrough.md +91 -0
- package/modules/one-on-ones/content.md +133 -0
- package/modules/one-on-ones/exercises.md +81 -0
- package/modules/one-on-ones/module.yaml +44 -0
- package/modules/one-on-ones/quick-ref.md +67 -0
- package/modules/one-on-ones/quiz.md +73 -0
- package/modules/one-on-ones/resources.md +37 -0
- package/modules/one-on-ones/walkthrough.md +69 -0
- package/modules/package.json +9 -0
- package/modules/prioritization-frameworks/content.md +130 -0
- package/modules/prioritization-frameworks/exercises.md +93 -0
- package/modules/prioritization-frameworks/module.yaml +41 -0
- package/modules/prioritization-frameworks/quick-ref.md +77 -0
- package/modules/prioritization-frameworks/quiz.md +73 -0
- package/modules/prioritization-frameworks/resources.md +32 -0
- package/modules/prioritization-frameworks/walkthrough.md +69 -0
- package/modules/prompt-engineering/content.md +123 -0
- package/modules/prompt-engineering/exercises.md +82 -0
- package/modules/prompt-engineering/game.yaml +101 -0
- package/modules/prompt-engineering/module.yaml +45 -0
- package/modules/prompt-engineering/quick-ref.md +65 -0
- package/modules/prompt-engineering/quiz.md +105 -0
- package/modules/prompt-engineering/resources.md +36 -0
- package/modules/prompt-engineering/walkthrough.md +81 -0
- package/modules/rag-fundamentals/content.md +111 -0
- package/modules/rag-fundamentals/exercises.md +80 -0
- package/modules/rag-fundamentals/module.yaml +45 -0
- package/modules/rag-fundamentals/quick-ref.md +58 -0
- package/modules/rag-fundamentals/quiz.md +75 -0
- package/modules/rag-fundamentals/resources.md +34 -0
- package/modules/rag-fundamentals/walkthrough.md +75 -0
- package/modules/react-fundamentals/content.md +140 -0
- package/modules/react-fundamentals/exercises.md +81 -0
- package/modules/react-fundamentals/game.yaml +145 -0
- package/modules/react-fundamentals/module.yaml +45 -0
- package/modules/react-fundamentals/quick-ref.md +62 -0
- package/modules/react-fundamentals/quiz.md +106 -0
- package/modules/react-fundamentals/resources.md +42 -0
- package/modules/react-fundamentals/walkthrough.md +89 -0
- package/modules/react-fundamentals/workshop.yaml +112 -0
- package/modules/react-native-fundamentals/content.md +141 -0
- package/modules/react-native-fundamentals/exercises.md +79 -0
- package/modules/react-native-fundamentals/module.yaml +42 -0
- package/modules/react-native-fundamentals/quick-ref.md +60 -0
- package/modules/react-native-fundamentals/quiz.md +61 -0
- package/modules/react-native-fundamentals/resources.md +24 -0
- package/modules/react-native-fundamentals/walkthrough.md +84 -0
- package/modules/registry.yaml +1650 -0
- package/modules/risk-management/content.md +162 -0
- package/modules/risk-management/exercises.md +86 -0
- package/modules/risk-management/module.yaml +41 -0
- package/modules/risk-management/quick-ref.md +82 -0
- package/modules/risk-management/quiz.md +73 -0
- package/modules/risk-management/resources.md +40 -0
- package/modules/risk-management/walkthrough.md +67 -0
- package/modules/running-effective-standups/content.md +119 -0
- package/modules/running-effective-standups/exercises.md +79 -0
- package/modules/running-effective-standups/module.yaml +40 -0
- package/modules/running-effective-standups/quick-ref.md +61 -0
- package/modules/running-effective-standups/quiz.md +73 -0
- package/modules/running-effective-standups/resources.md +36 -0
- package/modules/running-effective-standups/walkthrough.md +76 -0
- package/modules/solid-principles/content.md +154 -0
- package/modules/solid-principles/exercises.md +107 -0
- package/modules/solid-principles/module.yaml +42 -0
- package/modules/solid-principles/quick-ref.md +50 -0
- package/modules/solid-principles/quiz.md +102 -0
- package/modules/solid-principles/resources.md +39 -0
- package/modules/solid-principles/walkthrough.md +84 -0
- package/modules/sprint-planning/content.md +142 -0
- package/modules/sprint-planning/exercises.md +79 -0
- package/modules/sprint-planning/game.yaml +84 -0
- package/modules/sprint-planning/module.yaml +44 -0
- package/modules/sprint-planning/quick-ref.md +76 -0
- package/modules/sprint-planning/quiz.md +102 -0
- package/modules/sprint-planning/resources.md +39 -0
- package/modules/sprint-planning/walkthrough.md +75 -0
- package/modules/sql-fundamentals/content.md +160 -0
- package/modules/sql-fundamentals/exercises.md +87 -0
- package/modules/sql-fundamentals/game.yaml +105 -0
- package/modules/sql-fundamentals/module.yaml +45 -0
- package/modules/sql-fundamentals/quick-ref.md +53 -0
- package/modules/sql-fundamentals/quiz.md +103 -0
- package/modules/sql-fundamentals/resources.md +42 -0
- package/modules/sql-fundamentals/walkthrough.md +92 -0
- package/modules/sql-fundamentals/workshop.yaml +109 -0
- package/modules/stakeholder-communication/content.md +186 -0
- package/modules/stakeholder-communication/exercises.md +87 -0
- package/modules/stakeholder-communication/module.yaml +38 -0
- package/modules/stakeholder-communication/quick-ref.md +89 -0
- package/modules/stakeholder-communication/quiz.md +73 -0
- package/modules/stakeholder-communication/resources.md +41 -0
- package/modules/stakeholder-communication/walkthrough.md +74 -0
- package/modules/system-design/content.md +149 -0
- package/modules/system-design/exercises.md +83 -0
- package/modules/system-design/game.yaml +95 -0
- package/modules/system-design/module.yaml +46 -0
- package/modules/system-design/quick-ref.md +59 -0
- package/modules/system-design/quiz.md +102 -0
- package/modules/system-design/resources.md +46 -0
- package/modules/system-design/walkthrough.md +90 -0
- package/modules/team-topologies/content.md +166 -0
- package/modules/team-topologies/exercises.md +85 -0
- package/modules/team-topologies/module.yaml +41 -0
- package/modules/team-topologies/quick-ref.md +61 -0
- package/modules/team-topologies/quiz.md +101 -0
- package/modules/team-topologies/resources.md +37 -0
- package/modules/team-topologies/walkthrough.md +76 -0
- package/modules/technical-debt/content.md +111 -0
- package/modules/technical-debt/exercises.md +92 -0
- package/modules/technical-debt/module.yaml +39 -0
- package/modules/technical-debt/quick-ref.md +60 -0
- package/modules/technical-debt/quiz.md +73 -0
- package/modules/technical-debt/resources.md +25 -0
- package/modules/technical-debt/walkthrough.md +94 -0
- package/modules/technical-mentoring/content.md +128 -0
- package/modules/technical-mentoring/exercises.md +84 -0
- package/modules/technical-mentoring/module.yaml +41 -0
- package/modules/technical-mentoring/quick-ref.md +74 -0
- package/modules/technical-mentoring/quiz.md +73 -0
- package/modules/technical-mentoring/resources.md +33 -0
- package/modules/technical-mentoring/walkthrough.md +65 -0
- package/modules/test-strategy/content.md +136 -0
- package/modules/test-strategy/exercises.md +84 -0
- package/modules/test-strategy/game.yaml +99 -0
- package/modules/test-strategy/module.yaml +45 -0
- package/modules/test-strategy/quick-ref.md +66 -0
- package/modules/test-strategy/quiz.md +99 -0
- package/modules/test-strategy/resources.md +60 -0
- package/modules/test-strategy/walkthrough.md +97 -0
- package/modules/test-strategy/workshop.yaml +96 -0
- package/modules/typescript-fundamentals/content.md +127 -0
- package/modules/typescript-fundamentals/exercises.md +79 -0
- package/modules/typescript-fundamentals/game.yaml +111 -0
- package/modules/typescript-fundamentals/module.yaml +45 -0
- package/modules/typescript-fundamentals/quick-ref.md +55 -0
- package/modules/typescript-fundamentals/quiz.md +104 -0
- package/modules/typescript-fundamentals/resources.md +42 -0
- package/modules/typescript-fundamentals/walkthrough.md +71 -0
- package/modules/typescript-fundamentals/workshop.yaml +146 -0
- package/modules/user-story-mapping/content.md +123 -0
- package/modules/user-story-mapping/exercises.md +87 -0
- package/modules/user-story-mapping/module.yaml +41 -0
- package/modules/user-story-mapping/quick-ref.md +64 -0
- package/modules/user-story-mapping/quiz.md +73 -0
- package/modules/user-story-mapping/resources.md +29 -0
- package/modules/user-story-mapping/walkthrough.md +86 -0
- package/modules/writing-prds/content.md +133 -0
- package/modules/writing-prds/exercises.md +93 -0
- package/modules/writing-prds/game.yaml +83 -0
- package/modules/writing-prds/module.yaml +44 -0
- package/modules/writing-prds/quick-ref.md +77 -0
- package/modules/writing-prds/quiz.md +103 -0
- package/modules/writing-prds/resources.md +30 -0
- package/modules/writing-prds/walkthrough.md +87 -0
- package/package.json +1 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# RAG Fundamentals Walkthrough — Learn by Doing
|
|
2
|
+
|
|
3
|
+
## Before We Begin
|
|
4
|
+
|
|
5
|
+
**Diagnostic Question:** When you ask an LLM a question about your company docs, how does it "know" the answer? What if the answer wasn't in its training data?
|
|
6
|
+
|
|
7
|
+
**Checkpoint:** You recognize that RAG (Retrieval-Augmented Generation) lets LLMs use external knowledge. You fetch relevant chunks, add them to the prompt, and the model answers from that context.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Step 1: Chunk a Document
|
|
12
|
+
|
|
13
|
+
<!-- hint:code language="text" highlight="1,3" -->
|
|
14
|
+
|
|
15
|
+
**Task:** Take a 1–2 page document (or create one). Chunk it three ways: (a) fixed 100 tokens, (b) by paragraph, (c) recursive (try sentence, then paragraph). For each, note: chunk count, whether any chunk loses context, and where boundaries feel wrong.
|
|
16
|
+
|
|
17
|
+
**Question:** When would fixed-size fail? When would paragraph boundaries be better?
|
|
18
|
+
|
|
19
|
+
**Checkpoint:** The user produces chunks for all three strategies. They observe that fixed-size can split mid-sentence; paragraph preserves semantics but chunks may be uneven.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Step 2: Understand Embeddings (Conceptually)
|
|
24
|
+
|
|
25
|
+
<!-- hint:card type="concept" title="Embeddings" -->
|
|
26
|
+
|
|
27
|
+
**Task:** Without coding, reason about similarity. For "How do I reset my password?", rank these by how semantically close they are: (A) "Password reset instructions", (B) "The sky is blue", (C) "Forgot password? Click here." Explain your ranking.
|
|
28
|
+
|
|
29
|
+
**Question:** Why might keyword search match (A) and (C) but miss (B)? Why do embeddings help?
|
|
30
|
+
|
|
31
|
+
**Checkpoint:** The user ranks: (A) or (C) closest, (B) farthest. They understand embeddings capture meaning; "reset" and "forgot" are related even without shared words.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Step 3: Design the RAG Pipeline
|
|
36
|
+
|
|
37
|
+
<!-- hint:diagram mermaid-type="flowchart" topic="RAG pipeline" -->
|
|
38
|
+
|
|
39
|
+
**Task:** Sketch the full pipeline for "Answer questions from our company handbook." List: (1) What gets indexed, (2) Chunking strategy, (3) How retrieval works, (4) How the prompt is augmented, (5) What the model receives.
|
|
40
|
+
|
|
41
|
+
**Question:** What metadata would you store with each chunk? How would you filter (e.g., by section, date)?
|
|
42
|
+
|
|
43
|
+
**Checkpoint:** The user designs: handbook → chunk → embed → store; query → embed → retrieve → augment → generate. They propose metadata (section, page) and filtering.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Step 4: Tune Top-k
|
|
48
|
+
|
|
49
|
+
<!-- hint:buttons type="single" prompt="When would you choose 3 chunks vs 10?" options="3 for focus,10 for breadth,Depends on doc size" -->
|
|
50
|
+
|
|
51
|
+
**Task:** If you retrieve 3 chunks vs. 10 chunks, what changes? List pros and cons. When would you choose 3? When 10? What problem does re-ranking address?
|
|
52
|
+
|
|
53
|
+
**Question:** Why might more chunks hurt? How does re-ranking help?
|
|
54
|
+
|
|
55
|
+
**Checkpoint:** The user explains: 3 = focused, may miss context; 10 = broader, may add noise and use context. Re-ranking improves precision of top results before passing to the LLM.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Step 5: Build a Minimal RAG (Hands-On)
|
|
60
|
+
|
|
61
|
+
**Task:** Using a library (LangChain, LlamaIndex, or similar), build a minimal RAG: load 2–3 paragraphs, chunk them, embed, store in an in-memory vector store. Query and print the retrieved chunks. Then augment a prompt and call an LLM. Confirm the answer cites the retrieved text.
|
|
62
|
+
|
|
63
|
+
**Question:** What would you add for production? (Persistence? Metadata? Evaluation?)
|
|
64
|
+
|
|
65
|
+
**Checkpoint:** The user has a working pipeline: load → chunk → embed → store → query → retrieve → augment → generate. They can list next steps (persistence, eval, etc.).
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Step 6: Identify a Pitfall
|
|
70
|
+
|
|
71
|
+
**Task:** A RAG system returns wrong answers. It retrieves 5 chunks and passes them to the model. List 4 possible causes (chunking, retrieval, prompt, model) and one fix for each.
|
|
72
|
+
|
|
73
|
+
**Question:** How would you debug? What would you measure first?
|
|
74
|
+
|
|
75
|
+
**Checkpoint:** The user identifies: bad chunks (fix: better chunking), irrelevant retrieval (fix: tune k, threshold, re-rank), weak prompt (fix: clarify "only use provided context"), or model ignoring context (fix: stronger instructions, eval faithfulness).
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# React — Components, Hooks, and State Management
|
|
2
|
+
|
|
3
|
+
## What is React?
|
|
4
|
+
|
|
5
|
+
React is a JavaScript library for building user interfaces. It uses a component-based architecture where UIs are composed of reusable, isolated pieces.
|
|
6
|
+
|
|
7
|
+
## JSX
|
|
8
|
+
|
|
9
|
+
JSX is syntax extension that lets you write HTML-like markup inside JavaScript:
|
|
10
|
+
|
|
11
|
+
```jsx
|
|
12
|
+
const element = <h1>Hello, world!</h1>;
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Under the hood, JSX compiles to `React.createElement()` calls. You can embed JavaScript expressions with `{expression}`:
|
|
16
|
+
|
|
17
|
+
```jsx
|
|
18
|
+
const name = "Alice";
|
|
19
|
+
const element = <h1>Hello, {name}!</h1>;
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Components (Functional)
|
|
23
|
+
|
|
24
|
+
Modern React uses **functional components** — plain JavaScript functions that return JSX:
|
|
25
|
+
|
|
26
|
+
```jsx
|
|
27
|
+
function Greeting({ name }) {
|
|
28
|
+
return <h1>Hello, {name}!</h1>;
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Components accept **props** (properties) as their single argument. Props are read-only.
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
Props flow down from parent to child. They're the primary way to pass data:
|
|
37
|
+
|
|
38
|
+
```jsx
|
|
39
|
+
<Greeting name="Alice" />
|
|
40
|
+
function Greeting({ name }) {
|
|
41
|
+
return <p>Hi, {name}</p>;
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## State (useState)
|
|
46
|
+
|
|
47
|
+
**State** is data that changes over time. Use the `useState` hook:
|
|
48
|
+
|
|
49
|
+
```jsx
|
|
50
|
+
function Counter() {
|
|
51
|
+
const [count, setCount] = useState(0);
|
|
52
|
+
return (
|
|
53
|
+
<button onClick={() => setCount(count + 1)}>
|
|
54
|
+
Count: {count}
|
|
55
|
+
</button>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- `useState(0)` returns `[value, setter]`
|
|
61
|
+
- Calling the setter triggers a re-render
|
|
62
|
+
- State is isolated per component instance
|
|
63
|
+
|
|
64
|
+
## Effects (useEffect)
|
|
65
|
+
|
|
66
|
+
**Effects** handle side effects: fetching data, subscribing, DOM manipulation:
|
|
67
|
+
|
|
68
|
+
```jsx
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
document.title = `Count: ${count}`;
|
|
71
|
+
}, [count]); // Re-run when count changes
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- First argument: function to run
|
|
75
|
+
- Second argument: dependency array — effect runs when any dependency changes
|
|
76
|
+
- Empty array `[]` = run once on mount
|
|
77
|
+
|
|
78
|
+
## Event Handling
|
|
79
|
+
|
|
80
|
+
Attach handlers with camelCase props:
|
|
81
|
+
|
|
82
|
+
```jsx
|
|
83
|
+
<button onClick={handleClick}>Click</button>
|
|
84
|
+
<input onChange={(e) => setValue(e.target.value)} />
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
React uses synthetic events (cross-browser wrapper). Call `e.preventDefault()` to prevent default behavior.
|
|
88
|
+
|
|
89
|
+
## Conditional Rendering
|
|
90
|
+
|
|
91
|
+
Render conditionally with `&&`, ternaries, or early returns:
|
|
92
|
+
|
|
93
|
+
```jsx
|
|
94
|
+
{isLoggedIn && <Dashboard />}
|
|
95
|
+
{status === 'loading' ? <Spinner /> : <Content />}
|
|
96
|
+
if (!user) return <Login />;
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Lists and Keys
|
|
100
|
+
|
|
101
|
+
Map arrays to elements. **Keys** help React track identity:
|
|
102
|
+
|
|
103
|
+
```jsx
|
|
104
|
+
{items.map(item => (
|
|
105
|
+
<li key={item.id}>{item.name}</li>
|
|
106
|
+
))}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Keys must be unique among siblings. Use stable IDs, not array indices for dynamic lists.
|
|
110
|
+
|
|
111
|
+
## The React Rendering Cycle
|
|
112
|
+
|
|
113
|
+
When state changes, React re-renders. Here's the flow:
|
|
114
|
+
|
|
115
|
+
```mermaid
|
|
116
|
+
flowchart LR
|
|
117
|
+
A[State Change] --> B[Re-render]
|
|
118
|
+
B --> C[Virtual DOM Diff]
|
|
119
|
+
C --> D[DOM Update]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```mermaid
|
|
123
|
+
flowchart LR
|
|
124
|
+
A[State Change] --> B[Virtual DOM Diff]
|
|
125
|
+
B --> C[Reconciliation]
|
|
126
|
+
C --> D[Real DOM Update]
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
1. **State Change** — `setState` or similar triggers update
|
|
130
|
+
2. **Virtual DOM Diff** — React compares new tree with previous
|
|
131
|
+
3. **Reconciliation** — Determines minimal DOM operations
|
|
132
|
+
4. **Real DOM Update** — Only changed nodes are updated
|
|
133
|
+
|
|
134
|
+
This makes React efficient: full re-renders are cheap in memory; only minimal DOM mutations occur.
|
|
135
|
+
|
|
136
|
+
## Rules of Hooks
|
|
137
|
+
|
|
138
|
+
- Call hooks only at the **top level** — not inside loops, conditions, or nested functions
|
|
139
|
+
- Call hooks only from **React function components** or custom hooks
|
|
140
|
+
- Custom hook names must start with `use`
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# React Exercises
|
|
2
|
+
|
|
3
|
+
## Exercise 1: Toggle Button
|
|
4
|
+
|
|
5
|
+
**Task:** Create a `Toggle` component that shows "ON" or "OFF" and switches when clicked. Use `useState` with a boolean.
|
|
6
|
+
|
|
7
|
+
**Validation:**
|
|
8
|
+
- [ ] Clicking toggles between ON and OFF
|
|
9
|
+
- [ ] The displayed text updates on every click
|
|
10
|
+
- [ ] State is managed with a single boolean
|
|
11
|
+
|
|
12
|
+
**Hints:**
|
|
13
|
+
1. `useState(false)` gives you `[value, setValue]`
|
|
14
|
+
2. Toggle with `setValue(!value)` or `setValue(prev => !prev)`
|
|
15
|
+
3. Use a ternary or template literal for the display text
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Exercise 2: Input Mirror
|
|
20
|
+
|
|
21
|
+
**Task:** Create a component with a text input. Whatever the user types should appear in a `<p>` below in real time (controlled input).
|
|
22
|
+
|
|
23
|
+
**Validation:**
|
|
24
|
+
- [ ] Typing updates the paragraph immediately
|
|
25
|
+
- [ ] The input value is controlled by state
|
|
26
|
+
- [ ] Clearing the input clears the paragraph
|
|
27
|
+
|
|
28
|
+
**Hints:**
|
|
29
|
+
1. Use `useState("")` for the value
|
|
30
|
+
2. `onChange={(e) => setValue(e.target.value)}`
|
|
31
|
+
3. `value={value}` makes it a controlled input
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Exercise 3: Timer with useEffect
|
|
36
|
+
|
|
37
|
+
**Task:** Create a timer that counts up every second when mounted. Use `useEffect` with `setInterval`. Clean up the interval when the component unmounts.
|
|
38
|
+
|
|
39
|
+
**Validation:**
|
|
40
|
+
- [ ] The displayed number increments every second
|
|
41
|
+
- [ ] No interval leak on unmount (return cleanup from useEffect)
|
|
42
|
+
- [ ] Uses `useState` for the displayed count
|
|
43
|
+
|
|
44
|
+
**Hints:**
|
|
45
|
+
1. `useEffect` with `[count]` or `[]` — which do you need?
|
|
46
|
+
2. `return () => clearInterval(id)` in the effect
|
|
47
|
+
3. `setCount(c => c + 1)` avoids stale closures
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Exercise 4: Search Filter
|
|
52
|
+
|
|
53
|
+
**Task:** Given a static array of names (e.g., `["Alice", "Bob", "Carol", "Dave"]`), render them in a list. Add a search input that filters the list as the user types (case-insensitive).
|
|
54
|
+
|
|
55
|
+
**Validation:**
|
|
56
|
+
- [ ] Typing "al" shows only "Alice"
|
|
57
|
+
- [ ] Clearing the input shows all names
|
|
58
|
+
- [ ] Filtering is case-insensitive
|
|
59
|
+
- [ ] Uses `filter()` and does not mutate the original array
|
|
60
|
+
|
|
61
|
+
**Hints:**
|
|
62
|
+
1. Store the search term in state, not the filtered list
|
|
63
|
+
2. Derive filtered list: `names.filter(n => n.toLowerCase().includes(search.toLowerCase()))`
|
|
64
|
+
3. The list is derived state — no need for separate state
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Exercise 5: Form with Validation
|
|
69
|
+
|
|
70
|
+
**Task:** Create a simple form with a name input (required) and an email input (required, must contain `@`). Show an error message below each invalid field. Disable the submit button until the form is valid.
|
|
71
|
+
|
|
72
|
+
**Validation:**
|
|
73
|
+
- [ ] Submitting with empty fields shows errors
|
|
74
|
+
- [ ] Invalid email format shows an error
|
|
75
|
+
- [ ] Submit button is disabled when invalid
|
|
76
|
+
- [ ] Valid form enables submit
|
|
77
|
+
|
|
78
|
+
**Hints:**
|
|
79
|
+
1. Track `name`, `email`, and optionally `touched` / `errors` in state
|
|
80
|
+
2. Compute validity: `name.trim() && email.includes('@')`
|
|
81
|
+
3. Optionally show errors only after first submit or on blur
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
games:
|
|
2
|
+
- type: bug-hunt
|
|
3
|
+
title: "React Anti-Pattern Detective"
|
|
4
|
+
snippets:
|
|
5
|
+
- code: |
|
|
6
|
+
function Counter() {
|
|
7
|
+
const [count, setCount] = useState(0);
|
|
8
|
+
return (
|
|
9
|
+
<button onClick={() => count++}>Count: {count}</button>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
bugLine: 4
|
|
13
|
+
explanation: "Mutating state directly — count++ mutates state in place. React won't re-render. Use setCount(count + 1) instead."
|
|
14
|
+
hint: "Does count++ actually trigger a re-render?"
|
|
15
|
+
- code: |
|
|
16
|
+
function TodoList({ items }) {
|
|
17
|
+
return (
|
|
18
|
+
<ul>
|
|
19
|
+
{items.map((item) => (
|
|
20
|
+
<li>{item.text}</li>
|
|
21
|
+
))}
|
|
22
|
+
</ul>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
bugLine: 5
|
|
26
|
+
explanation: "Missing key prop — React needs a unique key for each list item to track identity and avoid rendering bugs. Use key={item.id} or a stable identifier."
|
|
27
|
+
hint: "What does React need to efficiently reconcile list items?"
|
|
28
|
+
- code: |
|
|
29
|
+
function DataFetcher() {
|
|
30
|
+
const [data, setData] = useState(null);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
fetch('/api/data')
|
|
33
|
+
.then((res) => res.json())
|
|
34
|
+
.then(setData);
|
|
35
|
+
}, [data]);
|
|
36
|
+
return <div>{data ? data.name : 'Loading...'}</div>;
|
|
37
|
+
}
|
|
38
|
+
bugLine: 6
|
|
39
|
+
explanation: "Infinite useEffect loop — the dependency array includes [data], so every time setData runs, the effect re-fires. Use [] for one-time fetch."
|
|
40
|
+
hint: "What happens when setData runs? Does the effect run again?"
|
|
41
|
+
- code: |
|
|
42
|
+
function SearchBar() {
|
|
43
|
+
const [query, setQuery] = useState('');
|
|
44
|
+
const handleSearch = () => {
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
fetchResults(query);
|
|
47
|
+
}, 500);
|
|
48
|
+
};
|
|
49
|
+
return <input onChange={(e) => setQuery(e.target.value)} />;
|
|
50
|
+
}
|
|
51
|
+
bugLine: 5
|
|
52
|
+
explanation: "Stale closure — the setTimeout callback captures query at callback creation. If the user types during the 500ms delay, fetchResults gets the old query. Use a ref or pass query explicitly."
|
|
53
|
+
hint: "What value of query does the setTimeout callback see when it runs?"
|
|
54
|
+
- code: |
|
|
55
|
+
function Parent() {
|
|
56
|
+
const [count, setCount] = useState(0);
|
|
57
|
+
const handleClick = () => setCount(count + 1);
|
|
58
|
+
return <Child onClick={handleClick} />;
|
|
59
|
+
}
|
|
60
|
+
function Child({ onClick }) {
|
|
61
|
+
return <button onClick={onClick}>Increment</button>;
|
|
62
|
+
}
|
|
63
|
+
bugLine: 3
|
|
64
|
+
explanation: "Recreated callback on every render — handleClick is a new function each render, causing Child to re-render unnecessarily. Wrap in useCallback for stable reference."
|
|
65
|
+
hint: "Is handleClick stable across Parent re-renders?"
|
|
66
|
+
- code: |
|
|
67
|
+
function ExpensiveList({ items }) {
|
|
68
|
+
const sorted = items.sort((a, b) => a.name.localeCompare(b.name));
|
|
69
|
+
return (
|
|
70
|
+
<ul>
|
|
71
|
+
{sorted.map((item) => <li key={item.id}>{item.name}</li>)}
|
|
72
|
+
</ul>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
bugLine: 3
|
|
76
|
+
explanation: "Sort mutates and runs every render — .sort() mutates the original array (can cause bugs) and recomputes on every render. Use useMemo with a copy: [...items].sort(...)."
|
|
77
|
+
hint: "Does sort mutate? Does this run on every render?"
|
|
78
|
+
|
|
79
|
+
- type: speed-round
|
|
80
|
+
title: "Hook Quick Fire"
|
|
81
|
+
rounds:
|
|
82
|
+
- question: "You need to store a number that changes when the user clicks a button. Which hook?"
|
|
83
|
+
options:
|
|
84
|
+
- "useEffect"
|
|
85
|
+
- "useState"
|
|
86
|
+
- "useRef"
|
|
87
|
+
- "useMemo"
|
|
88
|
+
answer: 1
|
|
89
|
+
timeLimit: 14
|
|
90
|
+
- question: "You need to fetch data when the component mounts. Which hook?"
|
|
91
|
+
options:
|
|
92
|
+
- "useState"
|
|
93
|
+
- "useEffect"
|
|
94
|
+
- "useCallback"
|
|
95
|
+
- "useRef"
|
|
96
|
+
answer: 1
|
|
97
|
+
timeLimit: 14
|
|
98
|
+
- question: "You need a mutable value that persists across renders but doesn't trigger re-renders when it changes. Which hook?"
|
|
99
|
+
options:
|
|
100
|
+
- "useState"
|
|
101
|
+
- "useEffect"
|
|
102
|
+
- "useRef"
|
|
103
|
+
- "useMemo"
|
|
104
|
+
answer: 2
|
|
105
|
+
timeLimit: 16
|
|
106
|
+
- question: "You're computing an expensive derived value from props. You want to avoid recomputing when other state changes. Which hook?"
|
|
107
|
+
options:
|
|
108
|
+
- "useCallback"
|
|
109
|
+
- "useEffect"
|
|
110
|
+
- "useMemo"
|
|
111
|
+
- "useRef"
|
|
112
|
+
answer: 2
|
|
113
|
+
timeLimit: 16
|
|
114
|
+
- question: "You're passing a callback to a memoized child; the callback depends on parent state. Which hook keeps the callback stable?"
|
|
115
|
+
options:
|
|
116
|
+
- "useMemo"
|
|
117
|
+
- "useEffect"
|
|
118
|
+
- "useCallback"
|
|
119
|
+
- "useRef"
|
|
120
|
+
answer: 2
|
|
121
|
+
timeLimit: 16
|
|
122
|
+
- question: "You need to share data (e.g. theme) with many components without prop drilling. Which hook?"
|
|
123
|
+
options:
|
|
124
|
+
- "useState"
|
|
125
|
+
- "useContext"
|
|
126
|
+
- "useMemo"
|
|
127
|
+
- "useRef"
|
|
128
|
+
answer: 1
|
|
129
|
+
timeLimit: 14
|
|
130
|
+
- question: "You need to store a DOM reference so you can call .focus() or .scrollIntoView(). Which hook?"
|
|
131
|
+
options:
|
|
132
|
+
- "useState"
|
|
133
|
+
- "useEffect"
|
|
134
|
+
- "useRef"
|
|
135
|
+
- "useContext"
|
|
136
|
+
answer: 2
|
|
137
|
+
timeLimit: 14
|
|
138
|
+
- question: "You need to run a side effect (e.g. subscribe to an event) when the component mounts and clean up when it unmounts. Which hook?"
|
|
139
|
+
options:
|
|
140
|
+
- "useState"
|
|
141
|
+
- "useEffect"
|
|
142
|
+
- "useCallback"
|
|
143
|
+
- "useMemo"
|
|
144
|
+
answer: 1
|
|
145
|
+
timeLimit: 14
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
slug: react-fundamentals
|
|
2
|
+
title: "React — Components, Hooks, and State Management"
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: "Master React's component model, hooks, and state management with hands-on exercises."
|
|
5
|
+
category: frameworks
|
|
6
|
+
tags: [react, javascript, frontend, components, hooks, state]
|
|
7
|
+
difficulty: beginner
|
|
8
|
+
|
|
9
|
+
xp:
|
|
10
|
+
read: 10
|
|
11
|
+
walkthrough: 30
|
|
12
|
+
exercise: 20
|
|
13
|
+
quiz: 15
|
|
14
|
+
quiz-perfect-bonus: 10
|
|
15
|
+
game: 25
|
|
16
|
+
game-perfect-bonus: 15
|
|
17
|
+
|
|
18
|
+
time:
|
|
19
|
+
quick: 5
|
|
20
|
+
read: 15
|
|
21
|
+
guided: 45
|
|
22
|
+
|
|
23
|
+
prerequisites: [typescript-fundamentals]
|
|
24
|
+
related: [react-native-fundamentals]
|
|
25
|
+
|
|
26
|
+
triggers:
|
|
27
|
+
- "How do React hooks work?"
|
|
28
|
+
- "What is useState and useEffect?"
|
|
29
|
+
- "How do I manage state in React?"
|
|
30
|
+
- "What are React components?"
|
|
31
|
+
|
|
32
|
+
visuals:
|
|
33
|
+
diagrams: [diagram-mermaid, diagram-flow]
|
|
34
|
+
quiz-types: [quiz-drag-order, quiz-timed-choice, quiz-fill-blank]
|
|
35
|
+
game-types: [bug-hunt, speed-round]
|
|
36
|
+
playground: javascript
|
|
37
|
+
web-embeds: true
|
|
38
|
+
|
|
39
|
+
sources:
|
|
40
|
+
- url: "https://react.dev"
|
|
41
|
+
label: "React Official Docs"
|
|
42
|
+
type: docs
|
|
43
|
+
- url: "https://react.dev/reference/react"
|
|
44
|
+
label: "React API Reference"
|
|
45
|
+
type: docs
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# React Quick Reference
|
|
2
|
+
|
|
3
|
+
## Hooks
|
|
4
|
+
|
|
5
|
+
| Hook | Purpose | Example |
|
|
6
|
+
|------|---------|---------|
|
|
7
|
+
| `useState(init)` | Local state | `const [v, setV] = useState(0)` |
|
|
8
|
+
| `useEffect(fn, deps)` | Side effects | `useEffect(() => {...}, [dep])` |
|
|
9
|
+
| `useRef(init)` | Mutable ref (no re-render) | `const ref = useRef(null)` |
|
|
10
|
+
|
|
11
|
+
## State Updates
|
|
12
|
+
|
|
13
|
+
| Pattern | Use When |
|
|
14
|
+
|--------|----------|
|
|
15
|
+
| `setValue(x)` | New value is independent |
|
|
16
|
+
| `setValue(prev => prev + 1)` | Depends on previous state |
|
|
17
|
+
| `setValue(prev => ({...prev, key: v}))` | Updating object state |
|
|
18
|
+
|
|
19
|
+
## useEffect Dependencies
|
|
20
|
+
|
|
21
|
+
| Array | Behavior |
|
|
22
|
+
|-------|----------|
|
|
23
|
+
| `[a, b]` | Run when a or b changes |
|
|
24
|
+
| `[]` | Run once on mount |
|
|
25
|
+
| Omitted | Run after every render (rare) |
|
|
26
|
+
| Return fn | Cleanup runs before next effect / unmount |
|
|
27
|
+
|
|
28
|
+
## Event Handlers
|
|
29
|
+
|
|
30
|
+
| Event | Handler |
|
|
31
|
+
|-------|---------|
|
|
32
|
+
| Click | `onClick={fn}` |
|
|
33
|
+
| Input | `onChange={(e) => setValue(e.target.value)}` |
|
|
34
|
+
| Submit | `onSubmit={(e) => { e.preventDefault(); ... }}` |
|
|
35
|
+
| Focus/Blur | `onFocus`, `onBlur` |
|
|
36
|
+
|
|
37
|
+
## Conditional Rendering
|
|
38
|
+
|
|
39
|
+
| Pattern | Use Case |
|
|
40
|
+
|---------|----------|
|
|
41
|
+
| `{cond && <A />}` | Render A or nothing |
|
|
42
|
+
| `{cond ? <A /> : <B />}` | Render A or B |
|
|
43
|
+
| `if (!cond) return null` | Early exit |
|
|
44
|
+
|
|
45
|
+
## Lists
|
|
46
|
+
|
|
47
|
+
```jsx
|
|
48
|
+
{items.map(item => (
|
|
49
|
+
<li key={item.id}>{item.name}</li>
|
|
50
|
+
))}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- Keys must be unique among siblings
|
|
54
|
+
- Prefer stable IDs over array index
|
|
55
|
+
|
|
56
|
+
## Decision: State vs Prop vs Derived
|
|
57
|
+
|
|
58
|
+
| Source | When to Use |
|
|
59
|
+
|--------|-------------|
|
|
60
|
+
| State | Data that changes, user can modify |
|
|
61
|
+
| Prop | Data from parent |
|
|
62
|
+
| Derived | Computed from state/props (filter, map, etc.) |
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# React Quiz
|
|
2
|
+
|
|
3
|
+
## Question 1
|
|
4
|
+
|
|
5
|
+
What does `useState` return?
|
|
6
|
+
|
|
7
|
+
A) The current state value only
|
|
8
|
+
B) The setter function only
|
|
9
|
+
C) An array of [value, setter]
|
|
10
|
+
D) The previous state value
|
|
11
|
+
|
|
12
|
+
<!-- ANSWER: C -->
|
|
13
|
+
<!-- EXPLANATION: useState returns a two-element array: [currentValue, setterFunction]. You typically destructure it as const [value, setValue] = useState(initial). -->
|
|
14
|
+
|
|
15
|
+
## Question 2
|
|
16
|
+
|
|
17
|
+
When does `useEffect` run if the dependency array is `[count]`?
|
|
18
|
+
|
|
19
|
+
A) Never
|
|
20
|
+
B) Only on initial mount
|
|
21
|
+
C) On every render
|
|
22
|
+
D) When count changes (and on mount)
|
|
23
|
+
|
|
24
|
+
<!-- ANSWER: D -->
|
|
25
|
+
<!-- EXPLANATION: The dependency array tells React when to re-run the effect. [count] means run when count changes. It also runs once on mount with the initial value. -->
|
|
26
|
+
|
|
27
|
+
## Question 3
|
|
28
|
+
|
|
29
|
+
Which is the correct way to update state based on the previous value?
|
|
30
|
+
|
|
31
|
+
A) `setCount(count + 1)`
|
|
32
|
+
B) `setCount(prev => prev + 1)`
|
|
33
|
+
C) `count = count + 1`
|
|
34
|
+
D) `this.setState({ count: count + 1 })`
|
|
35
|
+
|
|
36
|
+
<!-- ANSWER: B -->
|
|
37
|
+
<!-- EXPLANATION: When the new state depends on the previous state, use the functional form setCount(prev => prev + 1) to avoid stale closure bugs, especially in async or batched updates. -->
|
|
38
|
+
|
|
39
|
+
## Question 4
|
|
40
|
+
|
|
41
|
+
Why do we need keys when rendering a list in React?
|
|
42
|
+
|
|
43
|
+
A) To improve performance
|
|
44
|
+
B) To help React identify which items changed, were added, or removed
|
|
45
|
+
C) For accessibility
|
|
46
|
+
D) Keys are optional and not required
|
|
47
|
+
|
|
48
|
+
<!-- ANSWER: B -->
|
|
49
|
+
<!-- EXPLANATION: Keys help React's reconciliation algorithm track element identity across renders. Without stable keys, React may reuse DOM nodes incorrectly, leading to bugs when reordering or deleting items. -->
|
|
50
|
+
|
|
51
|
+
## Question 5
|
|
52
|
+
|
|
53
|
+
What is a controlled component?
|
|
54
|
+
|
|
55
|
+
A) A component that controls its children
|
|
56
|
+
B) An input whose value is driven by React state
|
|
57
|
+
C) A component that uses useController
|
|
58
|
+
D) A component wrapped in a form library
|
|
59
|
+
|
|
60
|
+
<!-- ANSWER: B -->
|
|
61
|
+
<!-- EXPLANATION: A controlled component is an form input whose value is set by React state (value={state}) and updated via onChange. The React component is the single source of truth. -->
|
|
62
|
+
|
|
63
|
+
## Question 6
|
|
64
|
+
|
|
65
|
+
Where can you call hooks?
|
|
66
|
+
|
|
67
|
+
A) Anywhere in the function body
|
|
68
|
+
B) Only inside event handlers
|
|
69
|
+
C) Only at the top level of a function component or custom hook
|
|
70
|
+
D) In class components
|
|
71
|
+
|
|
72
|
+
<!-- ANSWER: C -->
|
|
73
|
+
<!-- EXPLANATION: Hooks must be called at the top level — not inside loops, conditions, or nested functions. This ensures hooks are called in the same order on every render, which React relies on. -->
|
|
74
|
+
|
|
75
|
+
## Question 7
|
|
76
|
+
|
|
77
|
+
<!-- VISUAL: drag-order -->
|
|
78
|
+
|
|
79
|
+
Put these React render lifecycle stages in the correct order:
|
|
80
|
+
|
|
81
|
+
A) Component returns JSX (render output)
|
|
82
|
+
B) useState/useReducer initialize or return current state
|
|
83
|
+
C) DOM updates (browser paints)
|
|
84
|
+
D) useEffect runs (after paint)
|
|
85
|
+
|
|
86
|
+
<!-- ANSWER: B,A,C,D -->
|
|
87
|
+
<!-- EXPLANATION: React first runs the component function; hooks like useState return values (B). The component returns JSX (A). React commits to the DOM, browser paints (C). Then useEffect runs as a post-commit effect (D). -->
|
|
88
|
+
|
|
89
|
+
## Question 8
|
|
90
|
+
|
|
91
|
+
<!-- VISUAL: fill-blank -->
|
|
92
|
+
|
|
93
|
+
Complete the controlled input pattern:
|
|
94
|
+
|
|
95
|
+
```jsx
|
|
96
|
+
const [value, setValue] = useState('');
|
|
97
|
+
return (
|
|
98
|
+
<input
|
|
99
|
+
value={___0___}
|
|
100
|
+
onChange={(e) => setValue(e.target.value)}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
<!-- ANSWER: value -->
|
|
106
|
+
<!-- EXPLANATION: A controlled input's value prop is driven by React state. The value variable holds the current state, so value={value} makes React the single source of truth. -->
|