React - Js - Comprehensive Guide
React - Js - Comprehensive Guide
Figure: The React logo – an atom-like symbol reflecting React’s component-based UI library. React is “a
JavaScript library for building user interfaces” 1 . It emphasizes declarative programming, where you
describe the what of the UI (how it should look for a given state) rather than the how to update the DOM.
React is component-based 2 : you build encapsulated components that manage their own state, then
compose them to create complex UIs. Internally, React uses a Virtual DOM to efficiently batch and
minimize actual DOM updates 3 . Because of this architecture, React apps can have fast, responsive UIs
even as state changes frequently. Initially created by Jordan Walke at Facebook (Meta) 4 , React is now
maintained by Meta and a community of developers, and it supports both web and native (via React Native)
applications 5 . It follows a “learn once, write anywhere” philosophy – the same React concepts apply
whether you render to the browser DOM, a mobile platform, or even on the server.
React’s popularity comes from its performance and modularity. Key features include Virtual DOM
rendering (fast UI updates) 3 , component-based architecture (reusable UI pieces) 6 , and modern
Hooks for managing state and side effects. React also supports server-side rendering (SSR) and works well
with tools like Next.js for building SEO-friendly web apps. In summary, React lets developers build rich,
interactive UIs by breaking them into small, reusable pieces (components) that react to data (state/props)
changes 2 3 .
JSX
JSX (JavaScript XML) is a syntax extension used by React to describe UI elements. JSX looks like HTML, but
it’s actually JavaScript. For example, <h1>Hello, world!</h1> in JSX compiles to a
React.createElement call under the hood 7 . Formally, “JSX stands for JavaScript XML” and allows you to
1
write markup-like syntax directly in JavaScript 8 . This mix of HTML-like tags and JavaScript makes the code
more readable and closely ties UI structure to its rendering logic.
When you write JSX, a build tool like Babel transforms it into standard JavaScript. For example:
// JSX
const element = <h1 className="greeting">Hello, {userName}!</h1>;
Here, <h1 ...> turns into React.createElement('h1', props, children) 7 . Notice also that
JSX attributes differ from HTML: you use className instead of class , and htmlFor instead of for ,
because these are JavaScript identifiers (e.g. [3†L116-L120]). You can embed any JavaScript expression inside
JSX by wrapping it in curly braces {} , such as {userName} above. Overall, JSX is a convenient syntax
sugar – it is optional but widely used because it makes writing React components more intuitive.
• Functional Components (also called function components) – These are simple JavaScript functions
that accept props and return JSX. They have no this binding and are often shorter to write. With
the introduction of Hooks, functional components can also have their own state and lifecycle logic.
• Class Components – These are ES6 classes that extend React.Component . They have a
render() method that returns JSX, and can hold local state ( this.state ) and lifecycle methods
( componentDidMount , etc.).
React’s official guidance is to prefer functional components for new code, as they are simpler and more
concise. Functional components are typically faster and more lightweight, and with Hooks they can handle
state and side effects without writing classes 9 10 . In fact, “functional components are recommended
for most new development due to their simplicity, performance, and flexibility” 11 . Class components
are still valid (especially in older codebases) but entail more boilerplate: you must manage this , bind
event handlers if needed, and use lifecycle methods explicitly.
Example: Here are two equivalent components, one functional and one class, that render a greeting:
2
// Functional Component
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
// Class Component
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
Either can be used in JSX as <Welcome name="Alice" /> . The functional version is shorter and avoids
the render() and this syntax. Thanks to Hooks, functional components can hold state and use
lifecycle-like effects (covered later) without needing a class.
State, on the other hand, is internal and mutable data that belongs to a component. State holds
information that can change over time (often from user input or network requests). In class components,
you initialize state in the constructor (e.g. this.state = { count: 0 } ), and update it via
this.setState(...) . In functional components, you use the useState Hook (e.g. const [count,
setCount] = useState(0) ). Importantly, “state is similar to props, but it is private and fully controlled by
the component” 13 . When state changes, React re-renders the component to reflect the new values. State is
not visible to parent components unless explicitly passed up (via callbacks).
In summary: Props are inputs passed to a component (immutable inside it), whereas state is local data
managed by the component itself 12 13 . For example, a Counter component might accept an initial
count as a prop, but keep the current count in its own state to handle increments.
3
Lifecycle Methods
Class components have lifecycle methods, special methods that get called at different stages of a
component’s existence (mounting, updating, unmounting, etc.). These include:
With the introduction of Hooks, most of these lifecycle needs are handled by the useEffect Hook in
functional components (discussed below). However, understanding the lifecycle methods helps in cases
where class components are still used or when discussing equivalent Hook behavior.
Event Handling
React uses a synthetic event system that wraps native browser events for cross-browser compatibility.
Handling events in JSX is similar to handling DOM events, with a few differences 17 :
4
• You cannot return false to prevent default behavior as in plain HTML. Instead, you must call
event.preventDefault() inside your handler.
function Form() {
function handleClick(e) {
e.preventDefault(); // prevent default action
console.log('Button clicked!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
Here, handleClick receives a synthetic event object e . You can treat it like a normal DOM event; for
instance, calling e.preventDefault() stops a form submission 18 19 . React ensures the event object
e behaves consistently (it follows W3C standards for synthetic events 19 ). Note that in class components,
you often need to bind event handlers or use arrow functions to preserve this (see example in [61†L73-
L82]). In functional components, this is not an issue.
Conditional Rendering
In React, rendering different UI based on conditions is done using standard JavaScript conditionals 20 . You
can use if statements, the ternary operator ? : , logical && , etc., directly inside your JSX or before it.
The official docs state: “Conditional rendering in React works the same way conditions work in JavaScript” 20 .
Example: Suppose you want to render a greeting only if a user is logged in:
function Greeting(props) {
if (props.isLoggedIn) {
return <UserGreeting />;
} else {
return <GuestGreeting />;
}
}
Or using a ternary:
return (
<div>
{isLoggedIn
5
? <h1>Welcome back!</h1>
: <h1>Please sign up.</h1>}
</div>
);
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={logout} />;
} else {
button = <LoginButton onClick={login} />;
}
return <div>{button}</div>;
The key idea is that React elements are just JavaScript expressions, so you conditionally create or include
them using standard JS logic 20 . When the condition changes (e.g. login state updates), React automatically
updates the UI to match the new element tree.
However, whenever you render a list of elements, each element needs a unique key prop. As the React
docs explain, “Keys help React identify which items have changed, are added, or are removed.” 21 .
This is crucial for performance when updating lists.
• Provide a stable, unique key (often an ID from your data) on each list element:
<li key={item.id}>...</li> .
• Avoid using array indices as keys if the list order may change, because that can lead to bugs 22 .
function NumberList(props) {
const listItems = props.numbers.map((number) =>
<li key={number}>{number}</li>
);
6
return <ul>{listItems}</ul>;
}
Without keys, React will warn you and may not update the list correctly. The key’s value should uniquely
identify a list item among its siblings 21 . When state changes, React uses these keys to determine how to
update each element, rather than re-rendering the entire list.
With a controlled component, the value of the form element is set from React state, and changes
propagate via event handlers that update state. For example:
function NameForm() {
const [name, setName] = useState("");
function handleChange(event) {
setName(event.target.value);
}
function handleSubmit(event) {
alert('A name was submitted: ' + name);
event.preventDefault();
}
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={name} onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
In this example, the <input> ’s value is tied to the name state. On every keystroke, handleChange
updates the state. Thus the React state is “the single source of truth” for the form field 24 . This makes it easy
to control what happens on submit and to enforce constraints on input.
You can also create uncontrolled components using refs if you want to let the DOM handle the form data,
but controlled components are recommended for most cases. Controlled components ensure that form
data lives in React state, giving you full control over the inputs 24 .
7
Lifting State Up
Sometimes multiple components need to share the same changing data. React recommends that you lift
the shared state up to the closest common ancestor of the components that need it. As the React docs say,
“In React, sharing state is accomplished by moving it up to the closest common ancestor of the components that
need it. This is called ‘lifting state up.’” 25 .
For example, consider two sibling components that both display and edit a temperature in different units.
Rather than keep each input’s value in its own state, you move the temperature state to a parent (the
“Calculator” component). The parent then passes the current temperature to each child via props and
provides callbacks to update it. This way, the two inputs stay in sync and both reflect the same source of
truth.
Example pattern:
function Calculator() {
const [tempC, setTempC] = useState('');
function handleCelsiusChange(celsius) {
setTempC(celsius);
}
function handleFahrenheitChange(fahrenheit) {
const celsius = (fahrenheit - 32) * 5 / 9;
setTempC(celsius);
}
return (
<div>
<TemperatureInput
scale="C"
temperature={tempC}
onTemperatureChange={handleCelsiusChange}
/>
<TemperatureInput
scale="F"
temperature={(tempC * 9/5 + 32)}
onTemperatureChange={handleFahrenheitChange}
/>
</div>
);
}
Here, the Calculator holds the single tempC state and passes it (and update functions) down. This
ensures consistency. The key idea is “the component owns the shared state”, making it the “source of truth” for
related child components 25 .
8
Composition vs Inheritance
React’s preferred pattern for reusing code between components is composition rather than classical
inheritance. The official docs emphasize that “React has a powerful composition model, and we recommend
using composition instead of inheritance to reuse code between components.” 26 .
Composition means you combine simple components into more complex ones by nesting and passing
children or props, instead of subclassing. For example, a Dialog component can accept arbitrary children
content (via props.children or other function props) to render inside a generic container (this is called
containment) 27 . You might also pass props to specialize behavior (specialization), such as having a
generic Button component and creating an AlertButton by rendering Button with specific props.
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">Welcome</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
Here, FancyBorder doesn’t know ahead of time what its children will be – it just renders
props.children inside a styled <div> 27 . This is composition in action.
In short, use composition (nesting and props) to reuse behavior and UI, rather than relying on
inheritance. React’s model is built around combining components, not extending them 26 .
9
React Hooks
Hooks are a modern React feature that let you use state and other React features in functional components
(no classes needed). Hooks start with “use”. Some of the most important Hooks are:
• useState: Lets you add local state to a function component. You call
const [state, setState] = useState(initialValue) . For example, const [count,
setCount] = useState(0) . This declares a state variable count with initial value 0, and
setCount lets you update it. “useState is a Hook that lets you add React state to function
components.” 28 . Using Hooks means you can have stateful logic without writing a class.
• useEffect: Lets you perform side effects (data fetching, subscriptions, manual DOM changes,
logging, etc.) after the component renders. It combines what you might have done in
componentDidMount , componentDidUpdate , and componentWillUnmount into one API. You
pass it a function, and React will run it after flushing changes to the DOM. For example:
useEffect(() => {
document.title = `Clicked ${count} times`;
});
This effect runs after every render (by default). According to the docs: “By using [useEffect], you tell React that
your component needs to do something after render… We’ll refer to it as our ‘effect’, and call it later after
performing the DOM updates.” 29 . You can also return a cleanup function or specify dependencies to
optimize it, but the key is that useEffect runs your code when needed.
• useRef: Returns a mutable ref object with a .current property. It can be used to directly
reference DOM elements (via ref={myRef} ) or to hold any mutable value that persists across
renders without causing re-renders. It’s often used for accessing child DOM nodes or storing
previous values.
• useReducer: An alternative to useState for complex state logic. It works like a mini-Redux: you
provide a reducer function (state, action) => newState and an initial state. You get back
[state, dispatch] . You call dispatch({type: 'increment'}) to update state.
useReducer is useful for managing state transitions in a more predictable way.
• useContext: Lets a component subscribe to React Context. You pass a context object created by
React.createContext , and it returns the current context value. This simplifies consuming
context in functional components (no need for <Context.Consumer> ).
10
• Custom Hooks: You can create your own hooks (functions starting with use ) to reuse stateful logic
across components. A custom hook is just a function that may call other hooks.
By using Hooks, function components can manage state, run effects, use refs, and more, all without writing
a class. In essence, “Hooks don’t work inside classes. But you can use them instead of writing classes.” 30 . This
has made class components less necessary.
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
Here, useState(0) creates a count state variable. useEffect updates the document title after every
render (first mount and every update) 29 . This is conceptually the same as calling document.title in
componentDidMount and componentDidUpdate in a class.
Context API
React’s Context API provides a way to pass data through the component tree without having to pass props
at every level 31 . You typically use Context for “global” data like current user, theme, or locale that many
components need. The docs explain: “Context provides a way to share values like these between components
without having to explicitly pass a prop through every level of the tree.” 31 .
11
const ThemeContext = React.createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
// Option 1: using contextType (class component)
// static contextType = ThemeContext;
// return <button theme={this.context} />;
Here, Toolbar does not need to pass theme prop to ThemedButton . The ThemedButton reads the
current theme context value directly. This “skips” intermediate levels. Context makes it easy to share state
(like theme or auth) without prop drilling 31 .
Internally, React manages context efficiently. However, overusing Context for non-global data can reduce
reusability. The docs say to use Context “when some data needs to be accessible by many components.” 31 .
Error Boundaries
React Error Boundaries are special components that catch JavaScript errors anywhere in their child
component tree, preventing the whole app from crashing. To create an error boundary, you write a class
component that implements static getDerivedStateFromError(error) to update state on error,
and/or componentDidCatch(error, info) to perform side effects like logging.
The React docs note: “If you define componentDidCatch , React will call it when some child component
(including distant children) throws an error during rendering. This lets you log that error… A component with these
methods is called an error boundary.” 16 . For example:
12
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state to show fallback UI
return { hasError: true };
}
componentDidCatch(error, info) {
// You can log the error here
logErrorToService(error, info);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
Wrap parts of your app in <ErrorBoundary> . If any child throws an error in render or lifecycle, the
boundary catches it and displays the fallback UI instead 16 . Note: Error boundaries do not catch errors in
event handlers or async code – only during render, lifecycle, and constructors of their children.
Using Webpack or a similar bundler, you can split code like this:
function MyComponent() {
return (
<div>
{/* Suspense shows fallback content while loading */}
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
13
</div>
);
}
The React.lazy function “lets you render a dynamic import as a regular component” 32 . Internally, when
you render <OtherComponent /> , React will trigger the dynamic import('./OtherComponent') ,
fetch that code chunk, and then render it. While it’s loading, the <Suspense> component displays the
fallback (e.g. a loading spinner) 33 .
This approach ensures that code for OtherComponent is only loaded when MyComponent is rendered,
not on the initial app load. As the official docs explain, lazy loading “dramatically improve[s] the
performance” by avoiding loading code the user may never need 34 . (Create React App and tools like
Next.js support this out of the box.)
Portals
React Portals provide a way to render children into a DOM node that exists outside the DOM hierarchy of
the parent component 35 . Normally, rendering in React inserts elements into the DOM under the parent
component’s hierarchy. But with portals, you can “teleport” a child to a different part of the DOM.
In this example, even if <Modal> is used inside a deeply nested component, its output will be placed
inside the #modal-root element (perhaps a top-level <div> ). This is useful for UI elements like modals,
tooltips, or menus that should visually escape parent clipping or stacking contexts 36 .
Portals behave like normal React children in terms of events and context (events bubble up through the
React tree even if the DOM placement is different) 37 . The main difference is just the placement in the
DOM. As the docs say: “Portals provide a first-class way to render children into a DOM node that exists outside
the DOM hierarchy of the parent component.” 35 .
14
Higher-Order Components
A Higher-Order Component (HOC) is a pattern for reusing component logic. An HOC is “a function that
takes a component and returns a new component.” 38 . It’s not part of the React API per se, but a convention.
Essentially, an HOC wraps a component to inject props or behavior.
For example, Redux’s connect function is an HOC: it takes your component and returns a new one that is
subscribed to the Redux store. Similarly, you might write an HOC withLogger(Component) that returns
a new component which logs props on each render.
Basic form:
function withExtraProp(WrappedComponent) {
return class extends React.Component {
render() {
return <WrappedComponent extraProp="extra" {...this.props} />;
}
}
}
Render Props
A render prop is a technique for sharing code between components using a prop whose value is a function.
In practice, you create a component that receives a function via props, and then calls that function to know
what to render. The docs define it as “a function prop that a component uses to know what to render.” 39 .
For example, a <Mouse> component might track mouse position and provide the coordinates to its child
via a render prop:
15
*/}
{this.props.render(this.state)}
</div>
);
}
}
Here, <Mouse> doesn’t know what to display; it calls this.props.render(mouseState) and the
parent decides what UI to render at the current mouse coordinates. You can also use the special
children prop in the same way (passing a function as the child).
Render props allow sharing behavior (like tracking mouse or data fetching) without relying on inheritance.
As noted, you can implement an HOC in terms of a render prop, so they are related patterns 40 . In modern
React, Hooks often replace the need for render props, but the pattern is still useful and appears in some
libraries (e.g. React Motion 41 ).
Basics: Wrap your app in a router (e.g. <BrowserRouter> ). Define routes using <Routes> and
<Route> components. For example:
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
16
<Route path="*" element={<NotFoundPage />} />
</Routes>
</BrowserRouter>
);
}
• In React Router v6+, <Routes> is used instead of the old <Switch> 42 . Each <Route> uses an
element={...} prop to specify what to render.
• Nested routes can be created by having <Route> children or using the new nested Routes .
• Use hooks like useParams , useNavigate etc. for navigation and accessing URL parameters. For
example, let navigate = useNavigate() (replacing the old useHistory ) 43 , and then
navigate('/login') .
Advanced: - Protected routes (redirect if not authenticated). - Route layouts and nested <Routes> . - URL
parameters: <Route path="users/:id" element={<UserPage />} /> , access via
const { id } = useParams(); . - Query params: via useSearchParams or useLocation . - Lazy
loading route components using React.lazy for code splitting. - Scroll restoration, prefetching data, etc.
(React Router v7 has data APIs as well).
What's new in v6 (and beyond)? According to documentation, “Routes replaces Switch” and <Route
element={...}> replaces the old component or render props 42 . The navigation hook changed: use
useNavigate() instead of useHistory() to navigate programmatically 43 . Many route matching
behaviors are more intuitive (no need for exact, etc.).
Citing the dev blog: “In the latest version, <Routes> replaces <Switch> ... and useHistory is replaced
with useNavigate ” 42 43 .
React Router’s own docs and community blogs provide many examples and API details beyond this
summary.
The key Redux principles are: “Single Source of Truth” (the whole app state is in one store), “State is read-only”
(you never mutate state directly), and “Changes are made with pure functions” (reducers) 44 . As one source
explains, Redux is “a predictable state container designed to help you write JavaScript apps that behave
consistently…” 45 . This predictability comes from having all state transitions in one place (reducers) and
using pure functions, making it easier to reason about and test.
In practice with React, you create a Redux store (often with Redux Toolkit), write actions like { type:
'ADD_TODO', payload: {...} } , and reducers like:
17
function todosReducer(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return [...state, action.payload];
case 'REMOVE_TODO':
return state.filter(todo => todo.id !== action.payload.id);
default:
return state;
}
}
Your store holds the root reducer, and you dispatch actions like store.dispatch({type: 'ADD_TODO',
payload: newTodo}) to update state. In React components, you connect them to the store via the
react-redux library – either using the connect HOC or the useSelector / useDispatch hooks – to
read state and dispatch actions.
Middleware: Redux middleware like Redux Thunk or Redux Saga intercept dispatched actions for handling
side effects. For example, Redux Thunk lets you write action creators that return a function (a “thunk”)
instead of an action object. Thunks get dispatch and getState as arguments, so you can perform
async calls and dispatch real actions when ready. The Redux docs note that “Thunks are a standard approach
for writing async logic in Redux apps, and are commonly used for data fetching.” 46 .
Redux Toolkit: The modern recommended approach is to use Redux Toolkit (RTK), which simplifies setup.
RTK provides configureStore , createSlice , and other utilities to reduce boilerplate. For example,
createSlice generates actions and reducers for you. It also includes Redux Thunk by default, and adds
useful dev tools.
• Zustand: A lightweight state-management library. As its author describes: “Zustand is a small, fast
and scalable bearbones state-management solution using simplified flux principles. Has a comfy API
based on hooks, isn’t boilerplatey or opinionated.” 47 . With Zustand you create a store and use hooks
to read/write it. It’s great for simple global state without the ceremony of Redux.
• Recoil: A state-management library from Facebook for React. “Recoil is a state management library for
React” that provides atoms (state units) and selectors (derived state) 48 49 . It lets you manage
global state in a more granular, hook-friendly way (components subscribe to atoms and re-render
when they change). The Recoil team promotes it as “powerful and flexible” for complex state – it can
handle derived and async data via selectors 49 .
There are others too (MobX, Jotai, etc.), but Zustand and Recoil are popular recent alternatives that
integrate well with React’s hook model. They often require less boilerplate than Redux and can be better fit
for some apps.
18
Unit Testing with Jest and React Testing Library
Testing React components is typically done with Jest (a JavaScript testing framework) together with React
Testing Library (RTL). Jest provides the test runner, assertion library, and mocking utilities, while RTL
provides utilities to render components and query the DOM in a way that simulates user interaction.
React Testing Library (from the Testing Library family) “is a very light-weight solution for testing React
components… It provides light utility functions on top of ReactDOM and react-dom/test-utils, in a way that
encourages better testing practices.” 50 . It encourages you to test components as a user would: by finding
elements by text, labels, roles, etc., rather than relying on internal implementation details. For example:
In this Jest test, we render the Counter component, simulate a click event with RTL’s fireEvent , and
assert the expected text is present. RTL queries like getByText mimic how a user might find elements.
Importantly, React Testing Library works with any test runner (though Jest is the recommended one 51 ).
The docs note: “This library is not a test runner or framework (though we recommend Jest as our preference, the
library works with any framework).” 51 . Jest has built-in features like snapshot testing (useful for catching
unexpected UI changes) and powerful mocking.
In summary, Jest + RTL is the modern standard for testing React UIs: Jest handles the test environment, and
RTL provides accessible, user-centric queries to test component behavior 50 51 .
19
Performance Optimization: - Production Build: Always test performance using the production build of
React (development mode is slower and includes warnings) 52 . For example, with Create React App run
npm run build to generate optimized assets 53 . - React.memo: Wrap pure components with
React.memo to prevent unnecessary re-renders when props haven’t changed. - useMemo/useCallback:
Memoize expensive calculations or functions to avoid recomputing on every render. - Code Splitting: Lazy-
load routes/components with React.lazy and Suspense as discussed to reduce initial bundle size 54
33 . - Virtualization: For very long lists, use windowing libraries (like react-window or react-virtualized) to
only render visible items. - Avoid Inline Functions and Objects in Props: These create new references on
every render, possibly causing child re-renders. Prefer useCallback/useMemo or move definitions outside
render. - Debounce Frequent Updates: For input handlers or resize events, consider debouncing to reduce
state churn. - Keep Heavy Computation out of Render: Move it to useMemo or separate functions.
Anti-Patterns to Avoid: - Prop Drilling: Passing props through many levels just to reach a deep child. Use
Context or state management instead. - Mutating State Directly: E.g. doing this.state.count++ or
modifying an object in state. Always use setState or return new state. - Heavy Components: Don’t fetch
data or hold big state in one component that does too much; break it up. - Overusing Redux: Not all apps
need global state; sometimes useState or useContext is enough. - Ignoring Keys: Missing or
unstable keys in lists leads to rendering bugs 21 . - Too Many Refs: Overuse of refs for everything, instead
of state or props. - Side Effects in Render: Never cause side effects directly inside render (like fetching data
or updating global variables). Use effects/hooks for that. - Neglecting Cleanup: Forgetting to clean up
subscriptions or intervals in componentWillUnmount /cleanup functions. - Using Array Index as Key:
Unless items are static and never reordered, avoid key={index} as it harms list update performance 55 .
- Blocking the Main Thread: Very heavy computations in render or effect can freeze UI. Offload with web
workers if needed.
Profiling tools (React DevTools Profiler) can help identify which components re-render too often or take too
long. Following best practices above helps maintain a performant app.
• Typing Props and State: Define interfaces for component props and state. For example:
20
const [count, setCount] = useState<number>(0);
• JSX Typings: TSX allows JSX just like .jsx. Class components extend React.Component<Props,
State> .
Overall, TypeScript catches many errors at compile time (like prop type mismatches or undefined values). It
adds verbosity in some places but greatly improves maintainability in large codebases.
As a project grows, organize by feature or type. There is no single “correct” structure, but here are some
patterns:
• By Type: e.g.
src/
components/
Button.js
Modal.js
hooks/
useAuth.js
utils/
api.js
styles/
theme.css
App.js
index.js
• By Feature (Domain/Route): Each feature folder contains its components, styles, hooks. For
example:
21
src/
features/
login/
LoginPage.js
loginSlice.js (if using Redux)
dashboard/
Dashboard.js
Dashboard.css
app/
store.js
components/
NavBar.js
index.js
In Robin Wieruch’s 2025 article on folder structure, he notes: “Most React projects start with a src/ folder and
one src/[name].(js|ts) file where you will find something like an App component.” 56 . From there, once multiple
components exist, extract them into subfolders (e.g. a components/ folder). Feature-based organization
is also common, especially in larger apps, to keep related files together. Whatever convention you choose,
keep it consistent and logical. Name files after the component they export (e.g. Button.js exports
Button component).
Tools like Create React App or Vite generate a basic structure. From there, consider adding directories like
assets/ (for images), services/ or api/ (for backend calls), contexts/ (for custom context
providers), etc., based on your app’s needs.
This generates a build/ (or dist/ ) folder with static HTML/CSS/JS optimized for production 53 . You
can then serve these static files on any web server. Common deployment platforms include GitHub Pages,
Netlify, Vercel, AWS S3 + CloudFront, or Heroku. The exact steps depend on hosting, but the key is you only
need to serve the static files, as React apps are client-side.
Build optimization tips: - Ensure tree-shaking and minification are enabled (CRA and most bundlers do
this). - Use environment variables (e.g. process.env.NODE_ENV ) to switch behavior (e.g. API endpoints). -
Enable caching (long cache lifetime) with hashed filenames for static assets. - Compress assets (gzip/brotli)
for smaller download size. - Consider server-side rendering or static site generation for SEO if needed (using
Next.js or similar). - Audit bundle size (e.g. with Webpack Bundle Analyzer) to spot large dependencies.
22
Also, always verify you are testing the production build for performance as development builds are not
optimized 52 . Finally, monitor the live app with real-user metrics (e.g. Lighthouse, Web Vitals) to ensure it
meets performance and accessibility standards.
Interview Questions
Below are example React interview questions ranging from basic to advanced:
• Basic:
• What is React, and why use it over plain JavaScript?
• Explain the Virtual DOM and how React uses it.
• What is JSX, and why do we use it?
• What are components in React? Difference between functional and class components?
• What is the difference between props and state?
• How do you create a stateful component in React?
• How do you handle events (e.g. button clicks) in React?
• Intermediate:
• Advanced:
23
These questions cover a range of React concepts and are commonly asked at different skill levels. They test
understanding of React’s core features, state management, performance, and associated libraries.
14 15 React.Component – React
https://legacy.reactjs.org/docs/react-component.html
16 Component – React
https://react.dev/reference/react/Component
23 24 Forms – React
https://legacy.reactjs.org/docs/forms.html
24
31 Context – React
https://legacy.reactjs.org/docs/context.html
32 33 34 54 Code-Splitting – React
https://legacy.reactjs.org/docs/code-splitting.html
35 36 37 Portals – React
https://legacy.reactjs.org/docs/portals.html
42 43 What's new changes and features in React Router v6. - DEV Community
https://dev.to/naimeahmed/whats-new-changes-and-features-in-react-router-v6-1o0c
44 45Beginner's Guide to Redux. A Predictable State Container for… | by Ayush Verma | JavaScript in Plain
English
https://javascript.plainenglish.io/redux-javascript-library-da402be58bf3
25