Client Flashcards
Array Methods - map, filter, reduce, forEach, find
map() → Returns a new array.
filter() → Filters based on condition.
reduce() → Accumulates values.
forEach() → Iterates but doesn’t return a new array.
find() → Returns first matching element.
Arrow Functions
Concise syntax, inherits this. from outer scope, not for constructor
Cleaner and concise syntax for functions.
Does not bind its own this – inherits from the enclosing scope.
Arrow functions cannot be used as constructors.
Be cautious with this inside arrow functions (especially in React event handlers).
Avoiding Unnecessary Context Re-renders
Purpose: Minimize re-renders of components consuming context values.
When to Use:
When you’re using React context for global state and you want to avoid re-renders of components that don’t need the updated context.
You can wrap individual components with useContextSelector (from third-party libraries) to select a smaller part of the context.
When It Becomes Overkill:
For simple context values that don’t trigger many re-renders.
Using too many context values or deeply nested context can actually hurt performance.
Best practices while designing states
Use state only when data changes over time. Else use const or props. Derive rest from state or props. Avoid derived state to avoid redundancy.
Minimal State : Less state → Fewer bugs
Group Related State : Easier updates
Separate unrelated state to avoid unnecessary re-renders. Avoid Deep Nesting : Flatten state when possible. Minimize state objects or use primitives when possible.
Functional Updates : Avoid stale state issues
Lazy Initialization : Initial calculation only once
Local State vs Lifted State : Simplifies structure
Controlled Inputs : Form inputs synced with state, Predictable input handling
Performance for Large Lists : Store IDs, use virtualization, Avoid unnecessary re-renders
Separate UI & Server State : Loading/Error separate from data, Improves readability & avoids mixing concerns
Can custom hooks return JSX?
No, Custom hooks should return state, functions, or data – not JSX. If you return JSX, it’s a component, not a hook.
Can useCallback cause stale state issues?
Yes, if state is used inside the callback, and it’s not part of the dependencies.
Example (WRONG):
const [count, setCount] = useState(0); const increment = useCallback(() => { setCount(count + 1); // Using stale `count` }, []);
The callback captures count = 0 forever due to empty dependency array.
Correct Version:
const increment = useCallback(() => { setCount((prevCount) => prevCount + 1); }, []);
Always use functional updates inside setState when state is part of a memoized callback.
Can useCallback work with async functions?
Yes, but the async function is still re-created on dependency changes.
Example:
const fetchData = useCallback(async () => { const data = await fetch('/api'); console.log(data); }, []);
No special behavior for async – still a function reference.
Can useContext cause performance issues?
Yes, if large components depend on context values that change frequently.
Re-renders every consumer when context value changes, even if only part of the context is used.
Can useContext lead to stale state issues?
Rarely, because context re-renders the consumer when the value changes.
But if context value includes state, and you destructure it wrong, you can introduce stale state.
const { user } = useContext(UserContext);
If user changes but you cached it elsewhere, stale data issues may occur.
Always consume context values directly inside the component render scope.
Can useContext replace state management libraries like Redux?
For small apps, yes.
For large apps with complex state and performance concerns, Context alone can become problematic.
Context doesn’t solve state management complexity – it only avoids prop drilling.
Can useMemo memoize a component?
No, useMemo memoizes values, not React components.
For memoizing components, use React.memo instead.
Can useMemo result in a stale value problem?
Yes, if dependencies are incorrect or missing, you may get stale values.
Ensure all dependencies are specified accurately in the dependency array.
Example (WRONG):
const filteredList = useMemo(() => filterList(list), []);
If list changes, this memoized value won’t update, causing stale state.
Correct:
const filteredList = useMemo(() => filterList(list), [list]);
Can useMemo return a function?
Yes, but useCallback is preferred when memoizing functions.
useMemo is for values, useCallback is for functions.
Example:
const memoizedFunction = useMemo(() => () => doSomething(), []);
Better:
const memoizedFunction = useCallback(() => doSomething(), []);
Can you compare performance implications of using useState vs. useReducer in large applications?
Multiple state updates → Multiple re-renders.
Tightly coupled state variables can cause redundant updates.
Difficult to maintain when state dependencies increase.
Multiple state variables can cause many re-renders when updated independently. Single state object → one re-render per dispatch.
Complex State Updates Updating nested or dependent state can lead to stale state issues. Reducer centralizes logic, improving consistency.
Function Identity Inline setState functions may change frequently, causing unnecessary re-renders in children. dispatch is stable across renders, minimizing re-renders.
Can you convert an uncontrolled component to a controlled component?
Yes, initialize state with ref.current.value, then control it.
const inputRef = useRef(); const [value, setValue] = useState(''); useEffect(() => { setValue(inputRef.current.value); }, []);
<input ref={inputRef} value={value} onChange={(e) => setValue(e.target.value)} />
Can you explain useContext with an example? When is it preferred over passing props?
useContext accesses the value from React Context:
const UserContext = createContext(); const user = useContext(UserContext);
Preferred over props when:
Deep component trees → Avoid prop drilling.
Global state (e.g., theme, authentication).
Can you optimize performance with useReducer()?
Memoize the reducer (if heavy).
Memoize context values if using with Context.
Avoid re-creating action objects inside render
Split state into smaller reducers if it’s too complex.
Can you replace Redux with useReducer()?
For small to medium apps, useReducer() + Context can replace Redux. Redux is better for:
Large-scale apps.
Middleware support (e.g., for side effects).
DevTools debugging.
Can you think of a scenario where Virtual DOM might not provide a performance benefit?
Small Static UI: Minimal DOM updates → Overhead of diffing Virtual DOM is unnecessary.
Canvas / WebGL: Graphics handled outside DOM → React overhead adds no value.
Frequent Animations (e.g., charts): Constant re-renders → Virtual DOM diffing can become a bottleneck.
Takeaway: Heavy animations → React not always best.
Can you use useReducer() with Context API?
Yes, useReducer() is often combined with Context API to manage global state.
const StateContext = createContext();
const DispatchContext = createContext();
Provides state and dispatch globally.
Better than prop drilling.
Class vs Function Components
boilerplate, performance, memory weight, testing, reusability
Functional : Cleaner, less boilerplate. Potentially better (React optimizes function components with hooks, React.memo, Lighter without lifecycle machinery, Easier to test (pure functions), Hooks like useCustomHook() promote reuse
Class : Verbose with this binding, Slightly slower (more complex reconciliation in class), More memory overhead due to class instances, Harder to test due to this and lifecycle methods, Requires HOCs or render props for reuse
Class when legacy or needs complex lifeclycle ComponentDidMount
Closures
A function “remembers” the variables from its outer scope function even after the outer function has finished executing.
When a function is created inside another function, it has access to the outer function’s variables. If the inner function is returned or passed outside the outer function, it still retains access to those variables even after the outer function finishes execution.
function Counter() { const [count, setCount] = React.useState(0); function increment() { setCount(count + 1); } return <button onClick={increment}>Count: {count}</button>; }
Here, increment() closes over count. It remembers count even when the component re-renders.
Without closures, increment() would lose access to count.
Closures and React
State updates in React often use closures to remember previous values (e.g., in setState or useState).
Event handlers and callbacks (like those in useEffect) are closures that allow functions to remember state, props, or other values even after the component has re-rendered.
Optimization hooks like useCallback leverage closures to memoize functions and avoid unnecessary re-renders.
Closures allow React to manage private state and encapsulate logic within components, which leads to more modular and maintainable code.
Code Splitting (using React.lazy and Suspense)
Purpose: Break down your app into smaller bundles, so users only download what’s needed for the current page or component, reducing initial load time.
When to Use:
For large applications with multiple routes, where loading everything upfront would be inefficient.
When you have components or features that are not immediately needed (e.g., modal, settings page).
When It Becomes Overkill:
For small apps or apps where most components are always required immediately.
For small, fast-loading components, splitting them may cause more overhead than the benefit.
{error}
} ``` Key Concept: Validate on every onChange → State-based validation. Or, validate on submit: Validate all fields before submission.{count}
Welcome
:Please Sign In
}` In React, a fragment is a way to group multiple children's elements. Using a Fragment prevents the addition of unnecessary nodes to the DOM.Child State: {stateName}
; }; ``` | State no change when prop change. State derived from props - out of sync