React is a JavaScript library developed by Facebook for building user interfaces, especially single-page applications where data changes over time without reloading the page.
JSX stands for JavaScript XML. It allows writing HTML elements directly within JavaScript code. It makes writing and understanding React components easier.
A React component is a function or class that returns a piece of UI (JSX). A React element is an object representation of a UI node created by calling a component.
Functional components are React components written as JavaScript functions. They return JSX and can use hooks like useState
and useEffect
.
Class components are React components defined using ES6 classes. They extend React.Component
and have access to lifecycle methods and this.state
.
The virtual DOM is a lightweight in-memory representation of the real DOM. React uses it to detect changes and update the actual DOM efficiently.
React compares the new virtual DOM with the previous one using a diffing algorithm. It updates only the parts of the real DOM that changed, improving performance.
Props (short for properties) are inputs passed to components from parent components. They are read-only and used to pass data and event handlers.
State is a built-in object used to store dynamic data in a component. Unlike props, state is managed within the component and can change over time.
In class components, you use this.setState()
. In functional components, you use the setState
function returned by the useState
hook.
Default props are fallback values provided to a component in case no props are passed. They can be set using Component.defaultProps
.
Prop drilling refers to passing props through multiple levels of nested components, even if intermediate components do not use them, just to reach a deep child.
React uses camelCase syntax for event handlers (e.g., onClick
) and passes a synthetic event object to the handler function.
useState
is a hook that lets functional components have state. It returns an array with the current state and a function to update it.
useEffect
lets you run side effects like fetching data, setting up subscriptions, or updating the DOM after render in a functional component.
Side effects are operations that interact with the outside world (e.g., API calls, timers, modifying DOM) and don't belong in the main rendering logic.
By default, useEffect
runs after every render. You can control when it runs by passing a dependency array as the second argument.
Conditional rendering allows you to render different UI elements or components based on conditions (e.g., using if
, ternary operators, or &&
).
<div style={{ color: 'red' }}>
import './App.css'
and use class names.onChange
.useState
or form libraries like Formik.<></>
or <React.Fragment>
.{isLoggedIn ? <Dashboard /> : <Login />}
{show && <Modal />}
React.createContext
, Provider
, and useContext
.Context.Consumer
.React.memo
, useMemo
, and useCallback
.React.lazy
.React.lazy
to show a loader or placeholder.useEffect
runs after the DOM is painted.useLayoutEffect
runs synchronously before painting, blocking render.shouldComponentUpdate
with a shallow prop and state comparison.componentDidCatch
.useEffect
runs side effects like API calls.useRef
stores mutable values without causing re-renders.onChange
.ref
to access its value when needed.useEffect
with fetch
or axios
to get data on mount.Component.defaultProps
or default parameters.forwardRef
for controlled ref exposure.React.memo
prevents unnecessary re-renders of functional components.useCallback
returns a memoized version of a callback function.useMemo
returns a memoized value based on dependencies.React.lazy
and Suspense
.<React.Fragment>
or shorthand <>
.setState
: setCount(prev => prev + 1)
.useEffect
runs after the paint, useLayoutEffect
before the paint.useLayoutEffect
can block visual updates if misused.React.memo
, useMemo
, useCallback
).useRef
or createRef
.React.createElement()
.useRef
.import React from 'react'; function Greeting() { return <h1>Hello, World!</h1>; }
function Welcome(props) { return <h2>Hello, {props.name}</h2>; }
import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
function InputExample() { const [text, setText] = useState(''); return ( <input value={text} onChange={e => setText(e.target.value)} /> ); }
function Button({ handleClick }) { return <button onClick={handleClick}>Click Me</button>; }
useEffect(() => { fetch('https://api.example.com/data') .then(res => res.json()) .then(data => setData(data)); }, []);
function Status({ isLoggedIn }) { return isLoggedIn ? <p>Welcome!</p> : <p>Please log in.</p>; }
function List({ items }) { return ( <ul> {items.map(item => <li key={item.id}>{item.name}</li>)} </ul> ); }
function useToggle(initial) { const [state, setState] = useState(initial); const toggle = () => setState(prev => !prev); return [state, toggle]; }
const inputRef = useRef(); function focusInput() { inputRef.current.focus(); }
const Input = React.forwardRef((props, ref) => ( <input ref={ref} {...props} /> ));
const LazyComponent = React.lazy(() => import('./LazyComponent')); function App() { return ( <Suspense fallback={<div>Loading...</div>}> <LazyComponent /> </Suspense> ); }
const MemoizedComponent = React.memo(function Component({ value }) { return <p>{value}</p>; });
const style = { color: 'blue', fontSize: '20px' }; return <h1 style={style}>Styled Text</h1>;
function Form() { const handleSubmit = (e) => { e.preventDefault(); alert('Form submitted!'); }; return ( <form onSubmit={handleSubmit}> <button type="submit">Submit</button> </form> ); }
const ThemeContext = React.createContext(); function ThemedComponent() { const theme = useContext(ThemeContext); return <p>Theme is {theme}</p>; }
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } }
return ( <> <h1>Title</h1> <p>Paragraph</p> </> );
const reducer = (state, action) => { switch (action.type) { case 'increment': return { count: state.count + 1 }; default: return state; } }; const [state, dispatch] = useReducer(reducer, { count: 0 });
function CustomButton({ onClick, label }) { return <button onClick={onClick}>{label}</button>; }
const className = isActive ? 'active' : 'inactive'; return <div className={className}>Status</div>;
useEffect(() => { document.title = `You clicked ${count} times`; }, [count]);
useEffect(() => { inputRef.current.focus(); }, []);
<BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> </Routes> </BrowserRouter>
const navigate = useNavigate(); useEffect(() => { navigate('/login'); }, []);
<div className={`box ${isVisible ? 'show' : 'hide'}`}></div>
return isLoading ? <p>Loading...</p> : <p>Data loaded</p>;
function Card({ header, body }) { return ( <div> <h3>{header}</h3> <p>{body}</p> </div> ); }
const [show, setShow] = useState(false); <button onClick={() => setShow(!show)}>Toggle</button> {show && <p>Visible Content</p>}
function Button({ label = "Click me" }) { return <button>{label}</button>; }
function DataProvider({ render }) { const data = "Hello from render props!"; return render(data); } // Usage: <DataProvider render={(data) => <p>{data}</p>} />
function withLogger(Component) { return function WrappedComponent(props) { console.log('Rendering', Component.name); return <Component {...props} />; } }
useEffect(() => { const timer = setTimeout(() => { // do something }, 300); return () => clearTimeout(timer); }, [inputValue]);
useLayoutEffect(() => { // Runs before paint }, []);
// Jest & React Testing Library test('renders greeting', () => { render(<Greeting />); expect(screen.getByText(/hello/i)).toBeInTheDocument(); });
return ReactDOM.createPortal( <div>I’m a modal</div>, document.getElementById('modal-root') );
function Tabs({ children }) { return <div>{children}</div>; } Tabs.Panel = function Panel({ children }) { return <div>{children}</div>; };
useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); } }));
const resource = fetchData(); function Component() { const data = resource.read(); return <p>{data}</p>; }
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
const AuthContext = createContext(); function useAuth() { return useContext(AuthContext); }
const ThemeContext = createContext(); function ThemeProvider({ children }) { const [theme, setTheme] = useState('light'); return ( <ThemeContext.Provider value={{ theme, setTheme }}> {children} </ThemeContext.Provider> ); }
const FastComponent = React.memo(function({ name }) { return <p>Hi {name}</p>; });
<Suspense fallback={<div>Loading...</div>}> <LazyComponent /> </Suspense>
const useStore = create(set => ({ count: 0, increment: () => set(state => ({ count: state.count + 1 })) }));
const EventBus = createContext(); function useEventBus() { return useContext(EventBus); }
<Route path="dashboard" element={<Dashboard />}> <Route path="settings" element={<Settings />} /> </Route>
useEffect(() => { const handleKey = (e) => { if (e.key === 'Enter') alert('Enter pressed'); }; window.addEventListener('keydown', handleKey); return () => window.removeEventListener('keydown', handleKey); }, []);
const observer = new IntersectionObserver(entries => { if (entries[0].isIntersecting) { // Load content } }); observer.observe(ref.current);
navigator.clipboard.writeText('Copied text');
useEffect(() => { const onResize = () => setSize(window.innerWidth); window.addEventListener('resize', onResize); return () => window.removeEventListener('resize', onResize); }, []);
useEffect(() => { const update = e => setPos({ x: e.clientX, y: e.clientY }); window.addEventListener('mousemove', update); return () => window.removeEventListener('mousemove', update); }, []);
useEffect(() => { localStorage.setItem('count', count); }, [count]);
useEffect(() => { window.onscroll = () => { if (window.innerHeight + window.scrollY >= document.body.offsetHeight) { loadMore(); } }; }, []);
const id = useId(); return <label htmlFor={id}>Name</label><input id={id} />;
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} />
<ThemeProvider> <AuthProvider> <App /> </AuthProvider> </ThemeProvider>
useEffect(() => { console.log("State changed:", value); }, [value]);
const memoizedCallback = useCallback(() => { doSomething(); }, [dependency]);
const formReducer = (state, action) => ({ ...state, [action.name]: action.value }); const [form, dispatch] = useReducer(formReducer, { name: "", email: "" }); <input name="name" onChange={(e) => dispatch(e.target)} />
const [mounted, setMounted] = useState(false); useEffect(() => setMounted(true), []); if (!mounted) return null;
const [open, setOpen] = useState(false); const toggle = () => setOpen(prev => !prev);
function useDebounce(value, delay) { const [debounced, setDebounced] = useState(value); useEffect(() => { const handler = setTimeout(() => setDebounced(value), delay); return () => clearTimeout(handler); }, [value, delay]); return debounced; }
<button aria-label="Close" onClick={handleClose}>X</button>
function useLocalStorage(key, initialValue) { const [value, setValue] = useState(() => { const saved = localStorage.getItem(key); return saved ? JSON.parse(saved) : initialValue; }); useEffect(() => { localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); return [value, setValue]; }
useEffect(() => { fetch(`/api/user/${id}`).then(res => res.json()).then(setUser); }, [id]);
const LazyComponent = React.lazy(() => import('./MyComponent'));
useEffect(() => { inputRef.current.focus(); }, []);
items.map((item, i) => ( <motion.div key={i} initial={{ opacity: 0 }} animate={{ opacity: 1 }}> {item} </motion.div> ))
function usePrevious(value) { const ref = useRef(); useEffect(() => { ref.current = value; }); return ref.current; }
function useThrottle(value, delay) { const [throttled, setThrottled] = useState(value); const lastRan = useRef(Date.now()); useEffect(() => { const handler = setTimeout(() => { if (Date.now() - lastRan.current >= delay) { setThrottled(value); lastRan.current = Date.now(); } }, delay); return () => clearTimeout(handler); }, [value, delay]); return throttled; }
const showToast = () => { alert('This is a toast!'); }
class ErrorBoundary extends React.Component { state = { hasError: false }; static getDerivedStateFromError() { return { hasError: true }; } render() { return this.state.hasError ? <h1>Something went wrong</h1> : this.props.children; } }
<input value={name} onChange={e => setName(e.target.value)} /> <input defaultValue="default" />
document.documentElement.style.setProperty('--main-bg', dark ? '#000' : '#fff');
useEffect(() => { document.body.style.overflow = 'hidden'; return () => (document.body.style.overflow = 'auto'); }, []);
const Input = React.forwardRef((props, ref) => <input ref={ref} {...props} />);
MyComponent.propTypes = { name: PropTypes.string.isRequired, };
const api = process.env.REACT_APP_API_URL;
export const A = () => <div>A</div>; export const B = () => <div>B</div>;
setCount(c => c + 1); setCount(c => c + 1);
let isMounted = true; fetch(url).then(res => { if (isMounted) setData(res); }); return () => { isMounted = false; };
useEffect(() => { const id = setInterval(log, 1000); return () => clearInterval(id); }, []);
window.onerror = (msg) => console.error("Global Error:", msg);
await new Promise(res => setTimeout(res, 1000));
<div className="skeleton"></div> <style>.skeleton { background: #ccc; height: 20px; }</style>
async function fetchWithRetry(url, retries = 3) { try { return await fetch(url); } catch (err) { if (retries > 0) return fetchWithRetry(url, retries - 1); throw err; } }
{role === 'admin' ? <AdminPanel /> : <UserPanel />}
<ErrorBoundary> <MainComponent /> </ErrorBoundary>
import { FixedSizeList as List } from 'react-window'; <List height={150} itemCount={1000} itemSize={35} width={300}> {({ index, style }) => <div style={style}>Item {index}</div>} </List>
<img loading="lazy" src="image.jpg" alt="example" />
useEffect(() => { function handleClick(e) { if (!ref.current.contains(e.target)) onClose(); } document.addEventListener("mousedown", handleClick); return () => document.removeEventListener("mousedown", handleClick); }, []);
useEffect(() => { fetch("/api").then(res => res.json()).then(setData); }, []);
const expensiveValue = useMemo(() => compute(num), [num]);
import { CSSTransition } from "react-transition-group"; <CSSTransition in={show} timeout={300} classNames="fade"> <div>Content</div> </CSSTransition>
<input type="file" onChange={e => setFile(e.target.files[0])} />
<div className={isActive ? "active" : ""}>Hello</div>
useEffect(() => { const fetchData = async () => { const res = await fetch("/api"); const data = await res.json(); setData(data); }; fetchData(); }, []);
{items.map((item, i) => ( <div key={i} className={selected === i ? "selected" : ""} onClick={() => setSelected(i)}> {item} </div> ))}
navigator.clipboard.writeText("Copied text");
const [open, setOpen] = useState(false); <button onClick={() => setOpen(!open)}>Toggle</button> {open && <div>Accordion Content</div>}
const [fields, setFields] = useState([""]); const addField = () => setFields([...fields, ""]); const removeField = i => setFields(fields.filter((_, idx) => idx !== i));
const MemoItem = React.memo(({ value }) => <div>{value}</div>);
const [open, setOpen] = useState(false); <div onClick={() => setOpen(!open)}>Menu</div> {open && <ul><li>Item</li></ul>}
const ref = useRef(); ref.current.scrollIntoView({ behavior: "smooth" });
const [step, setStep] = useState(1); {step === 1 && <StepOne />} {step === 2 && <StepTwo />}
const refs = useRef([]); refs.current[index] = el; <input ref={el => refs.current[i] = el} />
const debounced = useDebounce(search, 300); useEffect(() => searchAPI(debounced), [debounced]);
useEffect(() => { const update = () => setWidth(window.innerWidth); window.addEventListener("resize", update); return () => window.removeEventListener("resize", update); }, []);
const handleChange = e => { const file = e.target.files[0]; const url = URL.createObjectURL(file); setPreview(url); };
const groups = items.reduce((acc, item) => { (acc[item.category] ||= []).push(item); return acc; }, {});
ReactDOM.createPortal(<Modal />, document.getElementById("portal"));
useEffect(() => { const handleKey = e => e.key === "Escape" && close(); document.addEventListener("keydown", handleKey); return () => document.removeEventListener("keydown", handleKey); }, []);
navigator.geolocation.getCurrentPosition(pos => console.log(pos.coords));
<div style={{ transition: "0.3s", opacity: show ? 1 : 0 }}>Content</div>
const syncScroll = () => { ref2.current.scrollTop = ref1.current.scrollTop; }; <div onScroll={syncScroll} ref={ref1}></div>
items.map(item => <div key={item.id}>{item.name}</div>)
const toggleTheme = () => setTheme(prev => (prev === "dark" ? "light" : "dark"));
const reset = () => setForm({ name: "", email: "" });
React.cloneElement(children, { newProp: value })
const [value, setValue] = useState(""); <input value={value} onChange={e => setValue(e.target.value)} />
const [dark, setDark] = useState(false); <div className={dark ? "dark" : ""}>App</div> <button onClick={() => setDark(!dark)}>Toggle Theme</button>
localStorage.setItem("token", "abc123"); const token = localStorage.getItem("token");
const inputRef = useRef(); useEffect(() => inputRef.current.focus(), []); <input ref={inputRef} />
<> <h1>Title</h1> <p>Text</p> </>
setUser(prev => ({ ...prev, name: "New Name" }));
this.handleClick = this.handleClick.bind(this);
Lift the shared state to the parent and pass via props.
const reducer = (state, action) => ({ ...state, [action.name]: action.value }); const [form, dispatch] = useReducer(reducer, {}); <input name="email" onChange={e => dispatch(e.target)} />
event.stopPropagation();
function Button({ label = "Click Me" }) { return <button>{label}</button>; }
useEffect(() => { fetch(url) .then(res => res.json()) .then(data => console.log(data)); }, []);
{items.map(item => <li key={item.id}>{item.name}</li>)}
const [show, setShow] = useState(false); {show && <div className="modal">Modal Content</div>}
useEffect(() => { fetch(`/api?page=${page}`).then(res => res.json()).then(setData); }, [page]);
const MemoComponent = React.memo(MyComponent);
const [count, setCount] = useState(0); <button onClick={() => setCount(count + 1)}>Increment</button>
<div style={{ color: "red", fontSize: "20px" }}>Hello</div>
const [type, setType] = useState("password"); <input type={type} /> <button onClick={() => setType(type === "password" ? "text" : "password")}>Toggle</button>
useEffect(() => { const timer = setTimeout(() => setShow(true), 1000); return () => clearTimeout(timer); }, []);
{items.filter(i => i.includes("a")).map(i => <div>{i}</div>)}
setOpen(prev => !prev);
const handleSubmit = e => { e.preventDefault(); // handle data };
import { useNavigate } from "react-router-dom"; const nav = useNavigate(); nav("/home");
const [online, setOnline] = useState(navigator.onLine); useEffect(() => { window.addEventListener("online", () => setOnline(true)); window.addEventListener("offline", () => setOnline(false)); }, []);
const components = { A: AComponent, B: BComponent }; const Dynamic = components[type]; <Dynamic />
// MyComponent.js export default function MyComponent() { return <div>Hi</div>; } // App.js import MyComponent from "./MyComponent";
style={{ transitionDelay: "0.5s" }}
<div>{user?.name}</div>
setItems(prev => prev.filter((_, idx) => idx !== index));
The `key` prop helps React identify which items have changed, been added, or removed in lists, improving performance when rendering lists of components.
You can conditionally render elements in React using JavaScript expressions like `if`, ternary operators, or logical `&&` operators within JSX. <div>{isLoggedIn ? "Welcome back!" : "Please log in"}
`componentWillMount` is called right before a component is mounted, whereas `componentDidMount` is called after the component has mounted and is ready for interactions.
React Router is a library for adding routing capabilities to a React application. It enables navigation between different components/views based on URL changes.
Using the `Route` component from React Router, you define the path and the component to render for that path. <Route path="/home" component={Home} />
`useContext` is a hook that allows you to access the value of a context without the need to pass it down manually through props.
`React.memo` is a higher-order component that memoizes a component, preventing unnecessary re-renders if the props have not changed.
You can handle form submissions in React by using the `onSubmit` event and controlling form elements with state. Example: <form onSubmit={handleSubmit}> <input type="text" value={inputValue} onChange={handleChange} /> <button type="submit">Submit</button> </form>
`propTypes` is a way to define the expected types of props that a component should receive, helping to validate the props passed to a component.
`React.StrictMode` is a wrapper component that helps identify potential problems in an application. It activates additional checks and warnings for components during development.
Fragments let you group multiple elements without adding extra nodes to the DOM. They are often used to return multiple elements from a component. <React.Fragment><div>Hello</div></React.Fragment>
The cleanup function inside `useEffect` is used to clean up side effects like subscriptions, timers, or event listeners when a component unmounts or before it re-renders.
You can optimize React performance by using `React.memo` for memoization, lazy loading components, using PureComponent, avoiding inline functions, and utilizing `useMemo` and `useCallback`.