// React Element (Virtual DOM Object)
const element = {
type: 'h1',
props: { className: 'greeting', children: 'Hello' }
};
// Lightweight JS object, not a real DOM node.
The Virtual DOM is a lightweight copy of the actual DOM in memory. When state changes:
JSX stands for JavaScript XML. It allows us to write HTML-like syntax directly in JavaScript. It is syntactic sugar that transpilers (like Babel) convert into React.createElement() calls.
React doesn't attach event handlers to nodes directly. Instead, it uses a single event listener at the root (Event Delegation) and wraps native browser events in SyntheticEvent objects. This ensures consistent behavior across different browsers.
Class Components:
componentDidMount: Runs after first render (API calls).componentDidUpdate: Runs after props/state change.componentWillUnmount: Runs before removal (cleanup).Functional Components (Hooks):
useEffect(() => { ... }, []): Equivalent to Mount.useEffect(() => { ... }, [prop]): Equivalent to Update.useEffect(() => { return () => { ... } }, []): Equivalent to Unmount.useEffect(() => {
console.log("Runs on every render");
});
useEffect(() => {
console.log("Runs once on mount");
}, []);
useEffect(() => {
console.log("Runs when count changes");
}, [count]);
useEffect(() => {
let ignore = false;
async function fetchUser() {
const res = await api.get(userId);
if (!ignore) setUser(res);
}
fetchUser();
return () => { ignore = true; }; // Cleanup race conditions
}, [userId]);
useEffect(fn): Runs after every render.useEffect(fn, []): Runs only once (on mount).useEffect(fn, [prop, state]): Runs on mount AND whenever prop or state changes.Cleanup Function: Returned from the effect. Runs before the component unmounts or before the effect re-runs.
useEffect(() => {
const timer = setInterval(tick, 1000);
return () => clearInterval(timer); // Cleanup
}, []);
// Correct
function Component() {
const [val, setVal] = useState(0);
if (val > 0) { ... }
}
// Incorrect (Breaks React)
function Component() {
if (condition) {
const [val, setVal] = useState(0); // Hook inside condition
}
}
// ESLint plugin 'eslint-plugin-react-hooks' enforces this rule.
// Error: React Hook "useState" is called conditionally.
React relies on the order of hooks to track state. If you put a hook inside an if statement, the order might change between renders, corrupting the state.
// Drilling
<GrandParent user={user} />
<Parent user={user} />
<Child user={user} /> // Only Child needs it
// Solution: Context
const UserContext = createContext();
// ...
<UserContext.Provider value={user}>...</UserContext.Provider>
// ...
const user = useContext(UserContext); // Access directly in Child
Passing props through intermediate components that don't need them.
Fixes:
// Bad (Index as key)
{items.map((item, index) => <li key={index}>{item}</li>)}
// Good (Unique ID)
{items.map(item => <li key={item.id}>{item.name}</li>)}
// If you delete the first item, React needs keys to know
// which DOM nodes to keep. With index keys, it might update
// the wrong component state.
It helps React identify which items have changed, are added, or are removed. Using index as a key is bad if the list order changes, as it causes bugs with component state.
function Parent() {
const [text, setText] = useState(""); // State lifted here
return (
<>
<Input value={text} onChange={setText} />
<Display text={text} />
</>
);
}
// FilterBar and ProductList are siblings.
// Filter state lives in their parent (ProductPage) so both can access it.
Moving state to the closest common ancestor of two components that need to share that state.
const [val, setVal] = useState("");
<input value={val} onChange={e => setVal(e.target.value)} />
// React controls the value
// Instant validation feedback
const handleChange = (e) => {
const newValue = e.target.value;
if (newValue.length <= 10) setValue(newValue); // Enforce limit
};
Form inputs whose value is controlled by React state. The "source of truth" is the React state, not the DOM.
// useEffect: Runs after paint (Async)
useEffect(() => { console.log("Visible"); });
// useLayoutEffect: Runs before paint (Sync)
useLayoutEffect(() => { console.log("Blocking"); });
// Measuring DOM element size before user sees it
useLayoutEffect(() => {
const { height } = ref.current.getBoundingClientRect();
setHeight(height);
}, []);
useEffect runs after the paint (async). useLayoutEffect runs synchronously after DOM mutations but before the paint. Use useLayoutEffect only if you need to measure DOM elements to prevent visual flickering.
// Class
class Welcome extends React.Component {
render() { return <h1>Hello, {this.props.name}</h1>; }
}
// Functional
function Welcome({ name }) {
return <h1>Hello, {name}</h1>;
}
// Functional components can use Hooks (useState, useEffect)
// Class components cannot.
Class: OOP, `this`, lifecycle methods, verbose. Functional: Functions, Hooks, simpler, modern standard.
const element = <h1>Hello</h1>;
// Transpiles to:
const element = React.createElement('h1', null, 'Hello');
// Embedding JS expressions
const element = <h1>Hello, {formatName(user)}</h1>;
JavaScript XML. Syntactic sugar for React.createElement(type, props, ...children).
return (
<React.Fragment>
<ChildA />
<ChildB />
</React.Fragment>
);
// Short syntax: <>...</>
// <div> cannot be a child of <tr>
function Columns() {
return (
<>
<td>Hello</td>
<td>World</td>
</>
);
}
A way to group a list of children without adding extra nodes to the DOM. <React.Fragment> or <>.
function Box({ children }) {
return <div className="box">{children}</div>;
}
// Usage
<Box>
<p>Content inside</p>
</Box>
function Layout({ children }) {
return (
<div>
<Header />
<main>{children}</main>
<Footer />
</div>
);
}
A special prop that allows passing components or elements inside another component's opening and closing tags.
function Button({ color = "blue" }) {
return <button className={color}>Click</button>;
}
// Class components used defaultProps
class Button extends React.Component { ... }
Button.defaultProps = { color: 'blue' };
You can define default values for props using default parameters in the function signature. function Comp({ name = "Guest" }).
class MyComponent extends React.PureComponent {
// Automatically implements shouldComponentUpdate
// with shallow prop comparison
}
const MyComponent = React.memo(function MyComponent(props) {
// Only re-renders if props change
});
A class component that implements shouldComponentUpdate with a shallow prop and state comparison. Functional equivalent is React.memo.
function handleClick(e) {
e.preventDefault(); // Works identically in all browsers
console.log(e.nativeEvent); // Access underlying browser event
}
// Before React 17, events were pooled (reused).
// e.persist() was needed to use event async.
// React 17+ removed pooling, so this is less of an issue now.
React's cross-browser wrapper around the browser's native event. It ensures events behave consistently across different browsers.
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
console.log(count); // Still 0! Update hasn't happened yet.
};
// React batches multiple updates into a single re-render
// to avoid unnecessary layout thrashing.
setCount(c => c + 1);
setFlag(true);
// Triggers only ONE re-render.
React batches state updates for performance. It doesn't update the state immediately but schedules an update.
// Wrong if called multiple times rapidly
setCount(count + 1);
// Correct
setCount(prevCount => prevCount + 1);
const toggle = () => setIsOpen(prev => !prev);
// Safe regardless of how many times it's clicked quickly
When the new state depends on the old state, pass a function: setCount(prev => prev + 1) to ensure you have the latest value.
function Form() {
const inputRef = useRef();
const handleSubmit = () => {
alert(inputRef.current.value); // Access DOM directly
};
return <input ref={inputRef} />;
}
// File inputs are always uncontrolled in React
<input type="file" ref={fileInputRef} />
Form inputs where the DOM handles the data, accessed via Refs, instead of React state.
Returns a mutable ref object. Changing ref.current does not trigger a re-render. Used for DOM access or storing mutable values.
Accepts a context object and returns the current context value. Subscribes the component to context changes.
Alternative to useState. Accepts a reducer of type (state, action) => newState. Good for complex state transitions.
JavaScript functions that start with "use" and can call other hooks. Allow sharing stateful logic between components.
Class: constructor -> render -> componentDidMount. Functional: Function body -> useEffect(() => {}, []).
Class: render -> componentDidUpdate. Functional: Function body -> useEffect(() => {}) or useEffect with deps.
Class: componentWillUnmount. Functional: useEffect cleanup function.
React's replacement for innerHTML. Risky because it can expose users to Cross-Site Scripting (XSS) attacks.
Styles are passed as an object with camelCased properties. style={{ backgroundColor: 'red' }}.
A CSS file where all class names are scoped locally by default. Imported as an object: import styles from './App.module.css'.
Library for writing actual CSS code to style components. Uses tagged template literals.
Rendering different UI based on state. {isLoggedIn ? <User/> : <Login/>}.
Use .map() to transform an array of data into an array of elements.
If the list order changes (sorting, filtering, inserting), using index as key can cause React to reuse state for the wrong component.
Since for is a reserved word in JS, React uses htmlFor for label tags.
Since class is a reserved word in JS, React uses className for CSS classes.
A tool for highlighting potential problems. In development, it renders components twice to detect side effects.
Data flows down from parent to child via props. Children cannot modify parent state directly (must use callbacks).
Building complex UIs from smaller, independent, reusable components.
A function that takes a component and returns a new component. Used for cross-cutting concerns (logging, auth).
A technique for sharing code between components using a prop whose value is a function. <DataProvider render={data => <Cat data={data}/>} />.
Allows a component to take a ref passed to it and forward it to a child DOM element.
Way to render children into a DOM node that exists outside the DOM hierarchy of the parent component (e.g., Modals, Tooltips).
Class components that catch JS errors in their child component tree, log errors, and display a fallback UI.
Loading components only when they are needed. const OtherComponent = React.lazy(() => import('./OtherComponent'));.
Component that lets you display a fallback (like a spinner) while children are finishing loading (e.g., lazy components or data).
React DevTools Profiler measures how often a React application renders and what the "cost" of rendering is.
The process through which React updates the DOM. It compares the new Virtual DOM with the old one and applies changes.
The new reconciliation engine in React 16. Enables features like concurrency and suspense by splitting work into chunks.