Unit 2: Component Design and Styling - Subjective Questions
INT252 — Web App Development With Reactjs • Practice Questions with Detailed Answers
20 questions
Define a functional component in ReactJS. Explain its structure, purpose, and advantages with a suitable example.
Answer:
A functional component is a JavaScript function that returns JSX describing the user interface. It accepts inputs called props and may use React Hooks to manage state and side effects.
function Welcome({ name }) {
return <h1>Welcome, {name}!</h1>;
}Important characteristics:
- It is a reusable and independent unit of UI.
- It returns JSX or
null. - It can receive data through props.
- Hooks such as
useStateanduseEffectcan add state and lifecycle behavior. - It is generally simpler and more concise than class components.
Functional components improve maintainability because the rendering logic and related behavior can be organized in a clear, modular function.
Explain how props-driven component reusability works in React. Illustrate your answer by designing a reusable Button component.
Answer:
Props-driven reusability means creating a component whose behavior and appearance can be customized through props instead of hard-coding values inside the component.
function Button({ label, variant = "primary", onClick, disabled = false }) {
return (
<button className={`button button-${variant}`} onClick={onClick} disabled={disabled}>
{label}
</button>
);
}The component can be reused as follows:
<Button label="Save" variant="primary" onClick={saveData} />
<Button label="Delete" variant="danger" onClick={deleteData} />Benefits:
- The same component supports different data and actions.
- Presentation and configuration are separated.
- Duplication is reduced.
- Changes to the common button structure can be made in one location.
- The component becomes easier to test and maintain.
Props should generally be treated as read-only. The child component should use callback props to request changes from its parent.
Describe component composition patterns in React. Compare composition using the children prop with composition using named props.
Answer:
Component composition means building complex interfaces by combining smaller components instead of creating one large component.
Composition with children:
function Card({ children }) {
return <section className="card">{children}</section>;
}
<Card>
<h2>Profile</h2>
<p>User information</p>
</Card>This approach is useful when the parent provides a common container while the caller controls the internal content.
Composition with named props:
function Layout({ header, sidebar, content }) {
return (
<div>
<header>{header}</header>
<aside>{sidebar}</aside>
<main>{content}</main>
</div>
);
}Named props are useful when a component has clearly defined regions with different responsibilities.
Comparison:
childrenis flexible and natural for nested content.- Named props make specific layout slots explicit.
- Both approaches reduce inheritance-based designs.
- Composition improves flexibility without forcing a component to know every possible child variation.
Explain the purpose of reusable component abstractions in React applications. What principles should be followed while creating such abstractions?
Answer:
A reusable component abstraction captures a repeated UI structure or behavior behind a clear interface. Examples include modal dialogs, form fields, tables, navigation menus, and alerts.
Principles for creating reusable abstractions:
- Define a focused responsibility for the component.
- Use props to support meaningful variations.
- Keep the public API small and predictable.
- Avoid adding options for hypothetical future requirements.
- Prefer composition when many variations are needed.
- Keep implementation details hidden from consumers.
- Make accessibility behavior part of the abstraction.
- Document required and optional props.
- Ensure that the abstraction works in different contexts.
For example, a reusable Modal may accept isOpen, title, children, onClose, and actions props. It should manage dialog semantics and keyboard behavior internally while allowing the caller to supply different content.
Discuss conditional rendering strategies in React. Explain how if statements, ternary expressions, logical AND, and early returns can be used appropriately.
Answer:
Conditional rendering displays different UI based on application state or props.
Using an if statement:
if (isLoading) {
return <p>Loading...</p>;
}This is suitable for large conditions or when a component should return early.
Using a ternary expression:
return isLoggedIn ? <Dashboard /> : <Login />;A ternary is appropriate for choosing between two alternative views.
Using logical AND:
{error && <p className="error">{error}</p>}This is useful when content should appear only when a condition is true. Developers should be careful with numeric values because an expression such as {count && <p>Items exist</p>} may render 0.
Using early returns:
if (!user) return <Login />;
return <Profile user={user} />;Early returns reduce nesting and make the main rendering path easier to understand.
The selected strategy should keep conditions readable and avoid deeply nested JSX.
Explain the concept of lifting state up in a React component hierarchy. Describe the data flow involved in a shared counter example.
Answer:
Lifting state up means moving shared state from sibling components into their closest common parent. The parent becomes the single source of truth and passes data and event handlers to the children through props.
function CounterApp() {
const [count, setCount] = useState(0);
return (
<>
<CounterDisplay count={count} />
<CounterControls onIncrement={() => setCount(count + 1)} />
</>
);
}Data flow:
CounterAppowns the state.CounterDisplayreceives the current count as a prop.CounterControlsreceives a callback prop.- The controls request an update by calling the callback.
- The parent updates its state.
- React re-renders both children with the new value.
This pattern prevents sibling components from maintaining conflicting copies of the same state. State should be lifted only as high as necessary, because placing all state at the top level can create unnecessary complexity and re-renders.
What are component responsibility boundaries? Explain how clearly defining these boundaries improves the design and maintenance of React applications.
Answer:
Component responsibility boundaries define which tasks belong inside a component and which tasks should be delegated to other components or services.
A well-designed component generally has one primary responsibility, such as displaying a product, managing a form, or coordinating a page section.
Benefits of clear boundaries:
- Components are easier to understand.
- Testing becomes more focused.
- Changes affect fewer files.
- Reuse becomes more practical.
- Presentation, state management, and data access can be separated.
- Components are less likely to become large and tightly coupled.
For example, a ProductPage may coordinate data and layout, a ProductDetails component may display product information, and a ProductForm component may manage form presentation and input events.
A component boundary should be reconsidered when a component contains unrelated concerns, has many conditional branches, requires excessive props, or cannot be tested without setting up unrelated behavior.
Compare major styling approaches used in React applications, including regular CSS, CSS Modules, inline styles, CSS-in-JS, and utility-first frameworks.
Answer:
React applications can use several styling approaches.
| Approach | Characteristics | Advantages | Limitations |
|---|---|---|---|
| Regular CSS | Styles are stored in global or shared files | Simple and familiar | Naming conflicts and unintended global effects |
| CSS Modules | Class names are locally scoped during build | Prevents collisions and supports normal CSS features | Requires build-tool support and creates generated class names |
| Inline styles | Styles are passed through the style prop |
Useful for dynamic values and local rules | Limited support for pseudo-classes, media queries, and selectors |
| CSS-in-JS | Styles are defined through JavaScript libraries | Dynamic styling and component-level organization | Runtime or tooling complexity may increase |
| Utility-first CSS | Small classes are combined directly in markup | Fast composition and consistent design tokens | Markup can become lengthy without reusable patterns |
The choice should depend on project size, team conventions, performance requirements, design-system needs, and the amount of dynamic styling required. Consistency within a project is usually more important than selecting a universally superior approach.
Explain the fundamental concepts of Tailwind CSS. Describe how utility classes can be used to style a React component.
Answer:
Tailwind CSS is a utility-first CSS framework that provides small, single-purpose classes for common styling properties.
function Notice() {
return (
<div className="rounded-md border border-blue-200 bg-blue-50 p-4 text-blue-900">
Your changes were saved.
</div>
);
}In this example:
rounded-mdcontrols border radius.borderadds a border.border-blue-200sets the border color.bg-blue-50sets the background color.p-4adds padding.text-blue-900sets the text color.
Tailwind classes are generated from a design system that includes spacing, colors, typography, sizing, flexbox, grid, and responsive variants.
Advantages:
- Styles can be applied directly where the structure is defined.
- Design values remain consistent.
- New CSS files are often unnecessary for common patterns.
- Responsive and state-based variants are built into the class syntax.
Reusable components should still be created when a group of utilities represents a repeated UI pattern.
What is the utility-first styling methodology? Explain its benefits and limitations when used in React projects.
Answer:
Utility-first styling builds an interface by combining small classes that each perform one styling task, such as setting padding, color, display, or font weight.
Benefits:
- Styles are close to the markup they affect.
- Naming new CSS classes is reduced.
- Design tokens encourage visual consistency.
- Responsive and interaction variants are easy to express.
- Components can be customized through props and conditional class names.
- Unused styles can often be removed during production builds.
Limitations:
- JSX may contain long class lists.
- Repeated class combinations can create duplication.
- Poorly organized utilities may make visual intent difficult to identify.
- Designers and developers must understand the framework's design scale.
- Complex selectors or highly specialized animations may still require custom CSS.
A practical solution is to use utility classes for composition and create reusable React components or helper functions for repeated patterns. Utility-first styling should support a consistent design system rather than replace component design.
Describe responsive design using Tailwind CSS breakpoints. Show how a React layout can change between small, medium, and large screens.
Answer:
Tailwind CSS uses responsive prefixes to apply utilities at specified minimum viewport widths. Unprefixed utilities apply to all sizes, while prefixed utilities override them at their breakpoint and above.
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
<ProductCard />
<ProductCard />
<ProductCard />
<ProductCard />
</div>Interpretation:
grid-cols-1creates one column by default.sm:grid-cols-2creates two columns at the small breakpoint and above.lg:grid-cols-4creates four columns at the large breakpoint and above.gap-4maintains consistent spacing at every size.
Tailwind encourages a mobile-first approach. Developers begin with the narrow-screen layout and add larger-screen enhancements using prefixes such as sm:, md:, lg:, and xl:.
Responsive design should consider content readability, touch targets, navigation behavior, spacing, and layout changes rather than merely shrinking elements.
Explain how reusable UI styling patterns can be implemented in React with Tailwind CSS. Include examples of variants and class composition.
Answer:
Reusable UI styling patterns group common visual rules into components while allowing controlled variations through props.
function Badge({ status }) {
const styles = {
success: "bg-green-100 text-green-800",
warning: "bg-yellow-100 text-yellow-800",
error: "bg-red-100 text-red-800"
};
return (
<span className={`rounded-full px-3 py-1 text-sm font-medium ${styles[status]}`}>
{status}
</span>
);
}Good practices:
- Keep shared layout and typography classes in the component.
- Use a controlled variant map instead of accepting arbitrary class strings everywhere.
- Merge external classes only when customization is part of the component contract.
- Separate structural classes from state or color variants.
- Use helper libraries when class merging and conditional combinations become complex.
- Preserve consistent focus, disabled, hover, and responsive states.
This approach keeps repeated patterns consistent while preventing every screen from inventing its own styling rules.
Define accessibility in the context of React applications. Explain why accessibility must be considered during component design rather than added later.
Answer:
Accessibility means designing applications so that people with different abilities can perceive, operate, understand, and interact with the interface.
Accessibility must be considered during component design because shared components are used across many screens. An inaccessible button, dialog, or form field can create the same problem throughout the application.
Important considerations:
- Use semantic HTML elements whenever possible.
- Ensure every interactive control is keyboard accessible.
- Provide visible focus indicators.
- Associate labels with form controls.
- Supply meaningful alternative text for informative images.
- Maintain sufficient color contrast.
- Communicate errors and status changes to assistive technologies.
- Manage focus when dialogs, menus, or dynamic regions open and close.
- Use ARIA only when native HTML does not provide the required semantics.
Building accessibility into reusable components reduces repeated effort and makes inclusive behavior the default for the entire application.
Explain semantic HTML practices in React. Distinguish between semantic elements and generic elements such as div and span.
Answer:
Semantic HTML elements communicate the meaning and structure of content to browsers, search engines, and assistive technologies.
Examples include:
<header>for introductory or navigational content.<nav>for major navigation links.<main>for the primary page content.<section>for a thematic grouping.<article>for an independent piece of content.<button>for an action.<form>for user input submission.<label>for identifying a form control.
<div> is a generic block container, while <span> is a generic inline container. They have no inherent meaning and should not replace semantic elements when a suitable element exists.
For example, this is preferable:
<button onClick={handleSave}>Save</button>instead of:
<div onClick={handleSave}>Save</div>A real button provides keyboard behavior, focus handling, and correct accessibility semantics automatically. Semantic HTML reduces the need for custom ARIA attributes and improves maintainability.
Design a reusable accessible form-field component in React. Explain the role of labels, IDs, validation messages, and ARIA attributes.
Answer:
A reusable form-field component should connect its label, input, help text, and error message through stable identifiers.
function FormField({ id, label, error, helpText, ...props }) {
const describedBy = error ? `${id}-error` : helpText ? `${id}-help` : undefined;
return (
<div>
<label htmlFor={id}>{label}</label>
<input
id={id}
aria-invalid={Boolean(error)}
aria-describedby={describedBy}
{...props}
/>
{helpText && !error && <p id={`${id}-help`}>{helpText}</p>}
{error && <p id={`${id}-error`}>{error}</p>}
</div>
);
}Accessibility roles of these elements:
htmlForconnects the label to the input'sid.aria-invalidcommunicates that the current value is invalid.aria-describedbyconnects the input to help or error text.- A stable error ID allows assistive technologies to identify the message.
- Visible error text provides information to all users.
The component should also support keyboard interaction, visible focus styles, appropriate input types, and clear validation timing.
Explain the difference between state and props in React. Describe when data should remain local and when it should be lifted to a parent component.
Answer:
Props and state both represent data used during rendering, but they have different ownership models.
Props:
- Are passed from a parent to a child.
- Are read-only from the child's perspective.
- Configure a component or provide callback functions.
- Support communication down the component tree.
State:
- Is owned and managed by a component.
- Can change over time through state update functions.
- Causes a component to re-render when updated.
- Represents data that the component needs to remember.
State should remain local when only one component needs it, such as whether a dropdown is open. It should be lifted to a common parent when multiple components need to read or update the same data, such as a selected item shared by a list and a details panel.
The goal is to keep state as close as possible to the components that use it while maintaining a single source of truth for shared data.
Analyze a React component that contains data fetching, form handling, layout markup, and several unrelated conditional branches. Explain how you would refactor it using responsibility boundaries and composition.
Answer:
A component with data fetching, form behavior, layout, and unrelated conditions has too many responsibilities. This makes it difficult to test, reuse, and modify safely.
Possible refactoring:
- Move data-fetching logic into a custom Hook or a dedicated data layer.
- Create a page-level container responsible for coordinating data and actions.
- Extract the form into a
UserFormcomponent. - Extract repeated display elements into focused components such as
UserSummaryandStatusMessage. - Move layout structure into a
PageLayoutcomponent. - Replace complex conditional branches with clearly named components or render functions.
- Pass required data and callbacks through explicit props.
- Keep business rules separate from presentational markup where practical.
The refactored structure might be:
<UserPage>
<PageLayout>
<UserSummary user={user} />
<UserForm user={user} onSubmit={saveUser} />
</PageLayout>
</UserPage>This design clarifies ownership, reduces cognitive load, and allows each part to be tested independently.
Compare composition and inheritance as approaches for sharing UI behavior in React. Why is composition generally preferred?
Answer:
Inheritance shares behavior by creating a subclass that extends a base class. Composition builds a component by combining smaller components, props, children, and Hooks.
React generally prefers composition because:
- It keeps relationships explicit in JSX.
- Components remain loosely coupled.
- Different child content can be inserted without changing the parent implementation.
- Behavior can be shared through Hooks and callback props.
- Component responsibilities remain easier to isolate.
- It avoids deep inheritance hierarchies that are difficult to understand.
For example, a reusable dialog can accept its content through children and its actions through an actions prop. It does not need a separate subclass for every possible dialog type.
Composition is not a rule against all forms of shared code. Utility functions, custom Hooks, and carefully designed abstractions can share logic. The important principle is to reuse behavior through explicit, flexible interfaces rather than relying on rigid component inheritance.
Explain how conditional rendering, loading states, empty states, and error states should be organized in a data-driven React component.
Answer:
A data-driven component should represent the meaningful states of the data request clearly and in an intentional order.
function UserList({ status, users, error }) {
if (status === "loading") return <LoadingIndicator />;
if (status === "error") return <ErrorMessage message={error} />;
if (users.length === 0) return <EmptyState />;
return <ul>{users.map(user => <UserItem key={user.id} user={user} />)}</ul>;
}Recommended organization:
- Check loading before attempting to display data.
- Show an actionable error message when the request fails.
- Provide an informative empty state when the request succeeds but returns no items.
- Render the primary content only when valid data is available.
- Use stable keys for lists.
- Extract complex states into reusable components.
- Avoid displaying contradictory states at the same time.
Clear state modeling improves user understanding and prevents incomplete or misleading interfaces.
Develop a strategy for making a Tailwind-styled React application responsive and accessible at the same time.
Answer:
Responsive styling and accessibility should be planned together because a layout that works visually on a large screen may be difficult to operate on a small screen or with a keyboard.
Strategy:
- Start with a readable mobile layout using unprefixed Tailwind utilities.
- Add larger-screen changes with
sm:,md:,lg:, orxl:prefixes. - Use responsive grid, flexbox, spacing, and visibility utilities carefully.
- Preserve logical reading and keyboard order when changing layout.
- Keep buttons and links large enough to activate comfortably.
- Use semantic elements such as
nav,main,button, andform. - Add visible focus styles such as
focus-visible:ring-2. - Avoid hiding essential information only at certain breakpoints.
- Test text wrapping, zoom, keyboard navigation, and screen-reader output.
- Check color contrast in every responsive variant.
Responsive design should adapt structure and spacing while preserving meaning, functionality, and access across devices.
Define a functional component in ReactJS. Explain its structure, purpose, and advantages with a suitable example.
Answer:
A functional component is a JavaScript function that returns JSX describing the user interface. It accepts inputs called props and may use React Hooks to manage state and side effects.
function Welcome({ name }) {
return <h1>Welcome, {name}!</h1>;
}Important characteristics:
- It is a reusable and independent unit of UI.
- It returns JSX or
null. - It can receive data through props.
- Hooks such as
useStateanduseEffectcan add state and lifecycle behavior. - It is generally simpler and more concise than class components.
Functional components improve maintainability because the rendering logic and related behavior can be organized in a clear, modular function.
Did this save you a night before the exam?
LPU Notes is free, and it stays free. Ads cover part of the server bill. The rest comes out of a student's own pocket: the domain, the storage, and keeping the site up through the weeks everyone needs it at once.
The payment button didn't load. An ad blocker or a filtered network is the usual reason. to try again.
Nothing here is ever locked, and nothing unlocks. Chip in only if it was worth it. What it pays for →