React Fundamentals
Assessment of core components, JSX, and unidirectional data flow.
What is JSX in React?
Comprehensive Study Guide: React Fundamentals: JSX, Components, State & Props
React is a declarative, component-driven JavaScript library designed to build fast, scalable user interfaces. In React's mental model, UI is a direct projection of application state: UI = f(state).
When building applications with React, understanding unidirectional data flow, the Virtual DOM reconciliation cycle, and component encapsulation is fundamental. Components accept external inputs called props (which remain immutable) and can encapsulate local private data known as state. When state changes occur via setter functions, React re-renders the component and calculates the minimal real-DOM mutations required.
Core Technical Competencies Tested in This Lab
JSX Compilation & Semantics
JSX is a syntax extension for JavaScript that compiles to React.createElement() or react/jsx-runtime calls. It allows developers to express HTML-like structure directly within JavaScript logic with full type-safety.
Props vs State Dichotomy
Props are read-only configuration passed downwards from parent to child components. State represents mutable local memory owned and maintained strictly within a component.
Unidirectional Data Flow
Data flows strictly top-down. To modify parent state from a child component, the parent must pass down a callback function via props (inversion of control).
Virtual DOM & Reconciliation
React keeps an in-memory representation of the UI tree. On state changes, it generates a new Virtual DOM tree and diffs it against the previous one using its heuristic O(n) reconciliation algorithm.
List Rendering & Keys
Keys provide a persistent identity to list elements across renders, enabling React to correctly track, insert, move, or delete nodes without unnecessary DOM destruction.
Controlled Form Components
Form inputs whose values are bound directly to React state, making React the single source of truth for form data rather than the browser DOM.
Architectural Code Patterns & Implementation Standards
Binding an input field directly to local state to enforce unidirectional flow and validation.
function SearchBar({ onSearch }) {
const [query, setQuery] = React.useState('');
const handleChange = (e) => {
setQuery(e.target.value);
onSearch(e.target.value);
};
return (
<input
type="text"
value={query}
onChange={handleChange}
placeholder="Search documents..."
/>
);
}Using ternary operators or checking length explicitly to prevent rendering unintended falsy zeros.
function NotificationBadge({ count }) {
// Bad: count && <span>{count}</span> (renders '0' if count === 0)
// Good:
return count > 0 ? (
<span className="badge">{count} new notifications</span>
) : (
<span className="text-muted">No unread alerts</span>
);
}Production Best Practices
- Always treat state as immutable: never mutate arrays or objects directly; use spread syntax (...prev) or functional state updates.
- Use stable, unique IDs (e.g. database UUIDs) for keys in lists—avoid using array indices if items can be reordered or filtered.
- Keep components small, focused, and single-responsibility for maximum reusability and testability.
- Lift state up to the closest common ancestor when sibling components need to synchronize data.
- Destructure props in component signatures for cleaner, self-documenting code.
Common Pitfalls & Anti-Patterns
- Mutating state directly (e.g. state.push(newItem)) which causes React to miss change detection and skip re-rendering.
- Passing function invocations instead of references to event handlers (e.g. onClick={handleClick()} instead of onClick={handleClick}).
- Overusing state for values that can be derived directly from existing props or state during render.
- Missing dependency array elements in hooks or neglecting cleanup functions in side effects.
Frequently Asked Conceptual Questions & Answers
Q1: Why does React require keys in mapped arrays?
Keys give elements a stable identity across renders. When an array changes (items inserted, deleted, or reordered), React's reconciliation algorithm matches old and new Virtual DOM nodes using keys. Without unique keys, React re-renders or mutates DOM nodes in place based on array index, which causes visual glitches and state bleeding across components.
Q2: What is the difference between controlled and uncontrolled components?
A controlled component has its form value managed entirely by React state via the 'value' prop and an 'onChange' handler. An uncontrolled component keeps its internal state inside the DOM, and React accesses it on-demand using a Ref (useRef). Controlled components are preferred for validation, dynamic formatting, and instant UI synchronization.
Q3: What happens under the hood when setState is called?
When you call a state updater function (e.g., setCount), React schedules a re-render of the component. In modern React (version 18+), state updates inside promises, timeouts, and native event handlers are automatically batched together into a single render pass to optimize performance.
Q4: Why shouldn't I use array indices as keys?
If items in a list are deleted, inserted at the beginning, or reordered, their indices change. React will assume the component at index 0 is the same as the previous component at index 0, leading to incorrect local state preservation (e.g. checked checkboxes or focus states remaining on the wrong items).
Ready to expand your skillset further?
Explore complete guided tutorials, interactive playgrounds, and comprehensive interview collections.
Explore Related Tools
Hand-picked utilities and calculators related to this tool.
