107 companion flashcards · AI-assisted study content · Open the deck →
This deck walks you through the core concepts of React, one of the most popular JavaScript libraries for building user interfaces. The cards start with the fundamentals, like what React is and how JSX and the Virtual DOM work, then move into how components are built and how data flows between them. From there, the deck expands into hooks, covering useState, useEffect, useContext, useReducer, useMemo, useCallback, and useRef, which are essential tools in any modern React developer's toolkit.
It's a great fit if you're just getting started with React and want a structured way to learn the vocabulary and ideas behind the library. It's also useful for developers who already write React code but want a clear, concise refresher on the building blocks, especially before interviews or when returning to a project after some time away.
To get the most out of these cards, try answering them in your own words before flipping to see the answer, and then write a small snippet of code that demonstrates the concept whenever possible. Spacing your review sessions over several days tends to be far more effective than cramming everything into one sitting, so revisit the deck regularly rather than trying to power through it in a single block.
React is a JavaScript library developed by Facebook for building user interfaces. At its core, React is component-based: an application is composed of small, reusable pieces of UI that each manage their own structure and behavior. Underneath this model sits React's most distinctive performance feature: the virtual DOM. The virtual DOM is a lightweight in-memory representation of the real DOM. When a component's state changes, React builds a new virtual tree, diffs it against the previous one, and applies only the minimal set of changes to the real DOM. This diffing process is called reconciliation.
Reconciliation is not a generic tree diff. React relies on heuristics to keep it fast and predictable: it compares elements by type, and when children are lists, it uses key props to match old elements with new ones. These heuristics let React decide the minimum number of DOM operations needed to reflect the latest state, which is what makes React efficient even for large, interactive applications.
To make components ergonomic to write, React extends JavaScript with JSX, a syntax that lets you write HTML-like markup directly inside JavaScript files. Browsers cannot run JSX as-is; tools like Babel transpile JSX into React.createElement() calls before the code reaches the browser. Because JSX is just JavaScript, you can freely embed expressions, call functions, and pass values as attributes — a flexibility that vanilla templates do not offer.
Components are the building blocks of a React application. A functional component is a plain JavaScript function that accepts an object of inputs called props and returns JSX. A class component is an ES6 class that extends React.Component and implements a render() method. While class components are still supported, modern React favors functional components because they are simpler, easier to test, and integrate naturally with the hooks API.
Props are how data flows from a parent component down to its children. They are read-only: the receiving component must never modify them. This unidirectional flow makes data movement predictable and easier to reason about. State, by contrast, is a component's private, mutable data. Whenever state changes, React re-renders the component to reflect the new value. In functional components, state is introduced with the useState hook, which returns a pair: the current value and a setter function that schedules an update.
State updates in React are asynchronous and batched. React groups multiple setter calls into a single re-render to avoid unnecessary work, so you cannot read the new state value immediately after calling the setter. When the new state depends on the previous one, the safer pattern is the functional updater form, setValue(prev => prev + 1), which guarantees the update is computed from the latest value and avoids stale-state bugs.
Beyond the two main forms of components, React supports several composition primitives. The children prop captures whatever JSX appears between a component's opening and closing tags, enabling patterns like cards, layouts, and wrappers. Controlled form components delegate their value to React state via the value and onChange props, while uncontrolled components let the DOM hold the value and expose it through a ref. Controlled components are generally preferred because they keep the source of truth in one place.
Hooks are functions that let functional components use state, side effects, contexts, and other React features without writing classes. useState returns a [value, setter] pair used to read and update local state. useEffect runs side effects such as data fetching, subscriptions, and manual DOM work after render completes. It accepts an effect function and an optional dependency array; a returned function from the effect is treated as cleanup that runs before the next effect and on unmount.
The dependency array dictates when an effect runs. An empty array means the effect fires only once on mount — useful for one-time setup and a direct replacement for componentDidMount. Passing a list of values means the effect re-runs whenever any of those values change. Omitting the array entirely causes the effect to run after every render, which is rarely what you want. Returning a cleanup function from an effect with an empty dependency array replicates componentWillUnmount, letting you release resources when the component leaves the screen.
Several hooks target specific problems. useContext reads the current value of a React context without needing a Context.Consumer wrapper. useReducer offers an alternative to useState for more elaborate state logic, where state transitions are expressed as actions handled by a reducer function. useMemo memoizes a computed value, recalculating only when its dependencies change, while useCallback memoizes a function reference so the same identity is preserved across renders — handy when passing callbacks to memoized children. In fact, useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).
Two hooks deserve separate mention. useRef returns a mutable object whose .current property persists across renders without triggering a re-render. It is the standard way to access DOM elements directly, as well as to store mutable values like timer IDs or previously seen props. useLayoutEffect is a variant of useEffect that fires synchronously after DOM mutations but before the browser paints, making it the right tool when you need to measure layout and re-render synchronously to avoid visual flicker.
Two universal rules govern all hooks: only call them at the top level of a component, never inside loops, conditions, or nested functions, and only call them from React function components or other custom hooks. These rules ensure hooks are invoked in the same order on every render, which is how React associates each hook with the correct internal slot.
Props are great for passing data, but threading the same value through several layers of components that don't actually use it is the problem known as prop drilling. The Context API solves it by letting a value be declared once near the top of the tree and read by any descendant that needs it. A context is created with React.createContext(defaultValue), supplied to a subtree via a Provider component that sets value, and consumed by any descendant with useContext(MyContext). When the provided value changes, every consumer re-renders.
Sometimes the right answer is not context but lifting state up. If two siblings need to stay in sync, you move the shared state into their closest common ancestor and pass it down as props. The ancestor becomes the single source of truth. To let a child send data back up to its parent — for instance, reporting a form submission — the parent passes a callback as a prop, and the child invokes it with the new value. This keeps the unidirectional flow intact even when information needs to travel against the tree.
Composition patterns reinforce the same idea. Higher-Order Components (HOCs) are functions that take a component and return an enhanced version, a technique useful for cross-cutting concerns like authentication, logging, and theming. Custom hooks go one step further: they are JavaScript functions whose names start with use and may call other hooks. They let you extract and reuse stateful logic across components without changing the component hierarchy. Both patterns are tools for reusing behavior, and the modern preference is usually custom hooks.
Conditional rendering is how React shows different UI based on state or props. The most common idioms are the ternary expression {isLoggedIn ? <Dashboard /> : <Login />} and short-circuit rendering with logical AND, {hasError && <Error />}. An early return inside the component body is also valid and is the cleanest choice when a branch should short-circuit the rest of the render.
JSX requires a component to return a single root element. React Fragments let you group multiple elements without introducing an extra DOM node, using either <React.Fragment>...</React.Fragment> or the shorthand <>...</>. The shorthand is more concise but cannot accept the key prop, so the long form is required when rendering lists. Portals go further: ReactDOM.createPortal(child, domNode) renders a child into a different part of the DOM entirely, which is the standard technique for modals, tooltips, and popups that need to escape overflow: hidden or stacking-context constraints of a parent.
Error handling has its own dedicated primitive: the Error Boundary. An Error Boundary is a class component that implements static getDerivedStateFromError() and/or componentDidCatch() to catch JavaScript errors in its child tree during rendering and in lifecycle methods, then display a fallback UI instead of a broken screen. Functional components cannot be error boundaries today — there is no hook equivalent of those static and instance methods — so libraries like react-error-boundary provide convenient wrappers around the class implementation.
Lifecycle methods themselves are a class-component concept. componentDidMount, componentDidUpdate, and componentWillUnmount mark the mounting, updating, and unmounting phases. Functional components replicate them through useEffect: an effect with an empty dependency array fires once on mount, one with dependencies fires when those values change, and a returned cleanup function fires on unmount and before the next run. <React.StrictMode> is a development-only wrapper that double-invokes certain functions and surfaces unsafe lifecycle usage and deprecated APIs — a useful safety net that has no effect in production builds.
Rendering lists in React is just mapping over an array to produce elements, but each element needs a stable key prop. Keys give every list item a stable identity so React can efficiently track, reorder, add, or remove items during reconciliation. Without proper keys, React may re-render entire lists or wrongly carry component state across items. The best key is a unique, stable identifier such as a database ID. The array index should be avoided when the list can be reordered, filtered, or modified, because index-based keys cause incorrect state mapping and subtle rendering bugs.
Events in React look like HTML but differ in important details. Event handlers are named in camelCase (onClick, onChange) and are passed function references rather than strings. A subtle but common mistake is writing onClick={handleClick()}, which invokes the function during render instead of when the user clicks — the correct form is onClick={handleClick}. React wraps native events in a SyntheticEvent, a cross-browser abstraction that exposes the same interface (preventDefault, stopPropagation, and so on) so handlers behave consistently across browsers.
Performance optimization in React is mostly about preventing unnecessary work. React.memo is a higher-order component that skips re-rendering a functional component when its props have not changed (using a shallow comparison). Combined with useMemo for computed values and useCallback for stable function identities, it lets you keep child components from re-rendering when their inputs have not actually changed. Lazy loading is another lever: React.lazy(() => import('./MyComp')) splits a component into its own bundle that is fetched on demand, reducing the initial download size. Pairing it with <Suspense fallback={<Loading />}> lets you display a fallback UI while the chunk loads. For very long lists, virtualization libraries such as react-window render only the rows visible in the viewport, keeping scroll performance smooth even with thousands of items.
useMemo memoizes a computed value so it is only recalculated when its dependencies change:const result = useMemo(() => expensiveCalc(a, b), [a, b]);useMemo memoizes a computed value: useMemo(() => val, [deps]).useCallback memoizes a function reference: useCallback(fn, [deps]).useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).useState returns [value, setValue]. Update with a new value: setValue(5), or with a functional updater when the new state depends on the old: setValue(prev => prev + 1). The functional form avoids stale state bugs.useDeferredValue(value) returns a deferred version of a value that lags behind the original, allowing React to render the urgent update first. It is useful for filtering large lists as the user types.useEffect runs asynchronously after paint. useLayoutEffect runs synchronously after DOM mutations but before paint, so it can measure layout without a visible flash. Use useLayoutEffect for DOM measurements.key prop to remount a component, or call state setters in an effect/derived state. In class components, static getDerivedStateFromProps can sync state from props.StrictMode. The 'use strict' directive is a JavaScript feature that catches silent errors and disallows sloppy-mode features in your own modules.Drill this topic
107 flashcards on React Framework — free, no signup needed to start.
Study React Framework flashcardsLearnWiki pages are generated with AI assistance from LearnCoachAssist's reviewed study catalog and may contain errors — verify anything critical against your course materials.