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.