0% found this document useful (0 votes)
5 views9 pages

React JS (Basic, Intermediate, Advanced)

The document provides a comprehensive overview of React JS concepts across basic, intermediate, and advanced levels. It covers topics such as state vs props, controlled vs uncontrolled components, testing, code splitting, and accessibility essentials. Each section includes concise explanations and practical examples to illustrate the concepts effectively.

Uploaded by

AryanKukreti
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views9 pages

React JS (Basic, Intermediate, Advanced)

The document provides a comprehensive overview of React JS concepts across basic, intermediate, and advanced levels. It covers topics such as state vs props, controlled vs uncontrolled components, testing, code splitting, and accessibility essentials. Each section includes concise explanations and practical examples to illustrate the concepts effectively.

Uploaded by

AryanKukreti
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

React JS - Basic Level

1) State vs Props

Answer (≈80–100 words):

Props are read‑only data passed from parent to child; they make components reusable and predictable. State is
internal, mutable data owned by the component (via hooks or class state) that drives re‑renders when updated.
Prefer pushing state up when multiple children need the same source of truth and compute derivations from
props when possible. Keep state minimal—store only what you can’t derive. Immutable updates and pure render
logic improve predictability and performance.

Example:

function Hello({ name }: { name: string }) { return <h1>Hello {name}</h1>; }


const [count, setCount] = useState(0);

2) Controlled vs Uncontrolled components


Answer (≈80–100 words):

Controlled inputs receive their value from React state and emit changes via callbacks—ideal for validation and
synchronization. Uncontrolled inputs store their state in the DOM; you read via refs on demand—ideal for
simple forms or performance‑sensitive cases. Controlled gives full control at the cost of more renders;
uncontrolled reduces overhead but limits validation. Choose per field; hybrid forms are common.

Example:

<input value={name} onChange={e=>setName([Link])} />


// uncontrolled
const ref = useRef<HTMLInputElement>(null);

3) Keys in lists & reconciliation


Answer (≈80–100 words):

Keys help React match elements across renders. Stable, unique keys prevent unnecessary unmount/mount,
preserving state and avoiding animation glitches. Never use indices when items can be reordered. Derive keys
from unique IDs. Correct keys minimize diffing cost and avoid subtle bugs (like wrong input retaining
focus/value).

Example:

{[Link](item => <Row key={[Link]} item={item} />)}


4) JSX to JavaScript (Babel)

Answer (≈80–100 words):

JSX is syntactic sugar compiled (by Babel/TS) into [Link] (or jsx runtime) calls. It describes UI
declaratively; expressions are embedded via {} . Compile steps include transforming JSX, TypeScript stripping,
and injecting helpers. Understanding this helps when debugging stack traces and optimizing component
boundaries.

Example:

<h1 className="t">Hi</h1>
// becomes jsx("h1", { className: "t", children: "Hi" })

5) useState basics & batching

Answer (≈80–100 words):

useState returns a value and a setter. Updates are batched within React events to minimize renders. Functional
updates ( set(x => x+1) ) avoid stale closures when next state depends on previous. Don’t mutate state directly—
always replace with new references for predictable diffs.

Example:

setCount(c => c + 1);

6) useEffect dependency basics

Answer (≈80–100 words):

Dependencies tell React when to re‑run an effect. Include all external values used. For one‑time effects, pass [] ;
for prop‑driven re-syncs, include those props. Cleanup functions run before re‑runs and on unmount. Extract
logic or use refs to avoid stale values. Lint rules help ensure correctness.

Example:

useEffect(()=>{ /* subscribe */ return ()=>{/* cleanup */} }, [id]);

7) Lifting state up

Answer (≈80–100 words):

When siblings need the same data, lift it to the nearest common ancestor and pass down via props. This avoids
duplication and divergence. Combine with memoization to prevent unnecessary re-renders. Consider Context for
deep trees to avoid prop drilling, or a store for complex graphs.

Example:

function Parent(){ const [value,setValue]=useState(''); return (<><A value={value}/><B onChange={setValue}/></

 

8) [Link] vs [Link]

Answer (≈80–100 words):

PureComponent (classes) and [Link] (functions) perform shallow prop/state comparison to skip re-renders.
They help when components receive stable props and re-render frequently. Beware: shallow compare misses
deep mutations; prefer immutability. Combine with useCallback / useMemo to stabilize function/derived props.

Example:

const Row = [Link](({item}:{item:Item}) => {/* … */});

9) forwardRef basics

Answer (≈80–100 words):

forwardRef lets you pass a ref through a component to a child (often a DOM node). This enables parent
components to imperatively focus/measure. Pair with useImperativeHandle to expose a controlled API rather than
raw DOM. Use sparingly to maintain declarative patterns.

Example:

const Input = [Link]<HTMLInputElement, Props>((p, ref)=>(<input ref={ref} {...p}/>));

10) Why Tailwind CSS?

Answer (≈80–100 words):

Tailwind provides low-level utility classes that compose into designs without leaving your JSX. Benefits: consistent
spacing/typography via a shared scale, rapid iteration, excellent tree‑shaking (small bundles), and fewer custom
CSS cascades. Compared to Bootstrap, Tailwind avoids rigid components and promotes design systems aligned
with your brand. For scalable component apps, co-locating styles with components reduces context switching
and CSS leaks.

Example:

<button className="px-3 py-2 rounded-lg bg-sky-600 text-white">Save</button>


React JS - Intermediate Level
1) Testing in React (Jest & React Testing Library)

Answer (≈80–100 words):

Write tests that reflect user behavior: render components, query by accessible roles/labels, and fire events. Mock
network boundaries and assert UI updates. Jest provides test runner/mocks; RTL encourages black‑box testing.
For API flows, use MSW to mock HTTP at the network layer and assert loading/error/success states. Keep unit
tests fast and add a few integration tests where logic crosses components.

Example:

render(<UserList/>);
expect(await [Link]('Ada Lovelace')).toBeInTheDocument();

2) Code splitting & lazy loading


Answer (≈80–100 words):

Split bundles to reduce initial payload and speed first paint. Use [Link] with Suspense for route‑ or
feature‑level chunks, and dynamic imports for on‑demand code. Combine with caching, prefetching, and
route‑based splitting. Measure with Lighthouse and keep critical path lean.

Example:

const Chart = [Link](()=>import('./Chart'));


<Suspense fallback={<Spinner/>}><Chart/></Suspense>

3) Dynamic imports

Answer (≈80–100 words):

import() returns a Promise that loads a module at runtime, enabling conditional and on‑demand loading. Great
for rarely used components, admin tools, or heavy libraries. Bundle analyzers help confirm splits. Handle loading
and error states gracefully.

Example:

if (needMap) { const { Map } = await import('./Map'); }

4) Optimizing large lists (10k+ rows)

Answer (≈80–100 words):


Virtualize with react-window or react-virtualized to render only visible rows. Memoize row components, use
stable keys, and avoid inline closures that change each render. Batch state updates, prefer CSS containment, and
offload heavy calculations to workers when necessary. Measure and iterate.

Example:

<List height={500} itemCount={[Link]} itemSize={32} width={800}>


{({index, style}) => <Row style={style} item={rows[index]} />}
</List>

5) useMemo vs useCallback
Answer (≈80–100 words):

useMemo memoizes computed values; useCallback memoizes functions. Both depend on stable dependency
arrays. Use them to avoid expensive recomputations or to keep referential stability for memoized children. Don’t
overuse—memoization has a cost. Profile first, then apply surgically.

Example:

const total = useMemo(()=>sum(items), [items]);


const onClick = useCallback(()=>doThing(id), [id]);

6) Context vs Redux (when to pick)

Answer (≈80–100 words):

Context avoids prop drilling for relatively static or localized global data (theme, auth). Redux adds predictable
updates, middleware, DevTools, and time‑travel—suited for complex, frequently updated shared state. For server
data, prefer React Query/SWR to manage caching, status, and refetching. Mix: Context for config + React Query
for server cache + Redux for client domain logic when needed.

Example:

const ThemeCtx = createContext<'light'|'dark'>('light');

7) Prevent unnecessary re-renders

Answer (≈80–100 words):

Use [Link] , stable callbacks ( useCallback ), and memoized values ( useMemo ). Avoid creating new
objects/functions inline when passed to memoized children. Split components to narrow re-render surfaces. For
lists, key by stable IDs. Measure with React DevTools Profiler to confirm improvements.

Example:
const handler = useCallback(()=>submit(form), [form]);

8) Custom hook: useDebounce


Answer (≈80–100 words):

A debounced value updates only after the input stops changing for a delay. This reduces API calls and re-renders
in typeahead UIs. Clean up timers on dependency changes and unmount.

Example:

function useDebounce<T>(value: T, delay=300){


const [v, setV] = useState(value);
useEffect(()=>{ const id = setTimeout(()=>setV(value), delay); return ()=>clearTimeout(id); }, [value, delay
return v;
}

 

9) Error Boundaries (class-based)

Answer (≈80–100 words):

Error Boundaries catch render lifecycle errors in their subtree and render a fallback UI. Implement with a class
component using static getDerivedStateFromError and componentDidCatch . They don’t catch event handler errors.
Use per-route or per-widget boundaries for resilience.

Example:

class Boundary extends [Link]<{}, {hasError:boolean}>{


state={hasError:false};
static getDerivedStateFromError(){ return {hasError:true}; }
componentDidCatch(err:any, info:any){ /* log */ }
render(){ return [Link] ? <Fallback/> : [Link]; }
}

10) API cancellation in React with cleanup

Answer (≈80–100 words):

Create an AbortController per request and abort in the effect cleanup or when parameters change. Guard state
updates after unmount to avoid warnings. Libraries like React Query handle this for you; with raw fetch, wire the
signal manually.

Example:
useEffect(()=>{ const c=new AbortController(); fetch(url,{signal:[Link]}); return ()=>[Link](); }, [url]);

 

React JS - Advanced Level


1) Hydration in [Link]: causes & fixes
Answer (≈80–100 words):

Hydration binds React event handlers to server‑rendered HTML. Errors occur when server and client markup
differ (time‑dependent values, random IDs, locale differences) or when client‑only code runs on the server. Fix by
ensuring deterministic rendering (guard on typeof window , move client‑only effects into useEffect ), use
suppressHydrationWarning for unavoidable differences, and prefer next/dynamic with ssr:false for client‑only
widgets.

Example:

{typeof window !== 'undefined' && <ClientOnly/>}

2) CSR vs SSR vs SSG vs ISR — when to use

Answer (≈80–100 words):

CSR renders entirely in the browser—great for apps behind auth with dynamic data. SSR delivers HTML per
request for better first paint and SEO with personalized data. SSG prebuilds static pages at build time for
maximal speed and cost efficiency. ISR periodically revalidates static pages at runtime, blending freshness and
performance. Choose per route based on change frequency and personalization needs.

Example:

Public marketing → SSG/ISR | Personalized dashboards → SSR/CSR

3) Caching (client + server)

Answer (≈80–100 words):

On the client, use React Query/SWR for request de‑duplication, background revalidation, and
stale‑while‑revalidate UX. On the server/CDN, set cache headers ( Cache-Control , ETag ) and leverage edge
caching. Carefully scope keys and invalidations to keep data consistent while minimizing refetches. Instrument to
detect stale data bugs.

Example:

const { data } = useSWR(['/api/items', filters], fetcher);


4) Handling API rate limits gracefully

Answer (≈80–100 words):

Respect 429 with exponential backoff and jitter, coalesce duplicate requests, and leverage caching and
incremental updates. Queue user actions locally and flush when allowed. Provide user feedback (toasts, disabled
buttons) and degrade gracefully. Prefer server‑side aggregation when possible.

Example:

const backoff = (n:number)=>[Link](1000*2**n + [Link]()*200, 30_000);

5) Optimistic UI updates

Answer (≈80–100 words):

Update the UI immediately and reconcile with the server response. Roll back on failure and notify the user.
Libraries like React Query provide onMutate/onError/onSettled to manage optimistic caches. Works best when
conflicts are unlikely or resolvable.

Example:

[Link](newItem, { onMutate: optimisticInsert, onError: rollback });

6) Building a component library for multiple teams

Answer (≈80–100 words):

Standardize design tokens, establish contribution guidelines, and document with Storybook. Provide versioned
packages, semantic releases, and CI for visual regression tests. Ship tree‑shakable ESM and type definitions.
Maintain strict a11y standards and theming, and avoid app‑specific logic.

Example:

Packages: tokens, icons, primitives, patterns

7) Folder structure for scalable apps

Answer (≈80–100 words):

Prefer feature‑first (domains) over type‑first (components/hooks separated). Co‑locate tests, styles, and fixtures.
Use boundaries for shared UI, core, and feature packages in a monorepo. Keep public APIs narrow and internal
paths private to simplify refactors.
Example:

src/features/orders/, src/features/inventory/, src/shared/ui/

8) Micro‑frontend architecture

Answer (≈80–100 words):

Split large apps into independently deployable fragments (Module Federation, single‑SPA). Align on contracts
(routing, events, design tokens). Watch for duplicate deps and runtime isolation. Use an orchestration shell and
enforce performance budgets.

Example:

Shell + remotes (orders, reports, admin)

9) Accessibility (a11y) essentials

Answer (≈80–100 words):

Use semantic HTML, proper labels, focus management, and logical tab order. Ensure color contrast and keyboard
operability. Announce dynamic content with ARIA live regions sparingly. Test with screen readers and automated
tools (axe). Bake a11y into the component library.

Example:

<label htmlFor="q">Search</label><input id="q" />

10) Core Web Vitals (LCP, INP, CLS)

Answer (≈80–100 words):

Improve LCP with optimized images, CDN, and critical CSS; INP with input responsiveness (avoid long tasks,
code‑split heavy handlers); CLS with size attributes and reserved space. Measure with web‑vitals, Lighthouse, and
RUM. Set budgets and regressions guards in CI.

Example:

import { onLCP, onINP, onCLS } from 'web-vitals'; onLCP([Link]);

You might also like