
Practice these 59 React coding interview questions with short solution approaches, grouped by difficulty, to prepare for your 2026 job interviews. Start with simple forms and state updates, then work through accessible components, asynchronous interfaces, and games.
Each question links to an interactive GreatFrontEnd exercise. The How to solve it notes explain an approach to the actual requirements; use the practice page for the complete specification and solution. Contact Form, Holy Grail, and Tweet also appear in the React workspace, but primarily test HTML and CSS.
If you're looking for more in-depth React interview preparation materials, also check out these resources:
UI coding rounds test how you turn requirements into working interfaces. These exercises give you practice with:
Work through the questions below in order of difficulty.
Build an accordion component that displays a list of vertically stacked sections with each containing a title and content snippet.
Practice question on GreatFrontEnd ->
How to solve it: Keep a Set of open section ids in state. On a header click, copy the previous set before toggling that id and storing the new set. More than one section can be open at once, so don't store a single index. Use a button for each header so it works with the keyboard.
Build a contact form which submits user feedback and contact details to a back end API.
Practice question on GreatFrontEnd ->
How to solve it: Use a native HTML form with method="post" and action="https://questions.greatfrontend.com/api/questions/contact-form". Give the labeled inputs the names name and email, use a textarea named message, and add a submit button labeled "Send". This exercise explicitly requires HTML-only submission and server-side validation, so do not intercept submission with JavaScript or add client-side validation.
Build the famous holy grail layout consisting of a header, 3 columns, and a footer.
Practice question on GreatFrontEnd ->
How to solve it: Use a flex column with min-height: 100vh for the page and a growing flex row for the three columns. Set the header to 60px, the footer to 100px, and the nav and aside to 100px wide without shrinking. Let main grow and the columns stretch to equal heights, keeping the footer at the bottom when content is short.
Build a list of progress bars that fill up gradually when they are added to the page.
Practice question on GreatFrontEnd ->
How to solve it: Store the number of bars and increment it on Add. Give each bar its own mounted state: render the fill at scaleX(0), then start a linear transition to scaleX(1) after mounting. Set transform-origin: left and a 2000ms duration so each bar fills independently without restarting older bars.
Build a calculator that computes the monthly mortgage for a loan.
Practice question on GreatFrontEnd ->
How to solve it: Read the form with FormData on submission and validate finite, positive values. Let P be the principal, r = annualRate / 100 / 12, and n = years * 12; calculate payment = P * r / (1 - 1 / (1 + r) ** n). Total paid is payment * n, and interest is that total minus P. Reject nonfinite results and format the three amounts as currency to two decimal places.
Build a component that books a flight for specified dates.
Practice question on GreatFrontEnd ->
How to solve it: Keep the trip type and date values in state. Show the return-date input only for round trips. Validate on submission that required dates are present, neither relevant date is in the past, and the return date is not before departure. Compare date-only values consistently with the local calendar date, then show the requested one-way or round-trip confirmation.
Generate a table of numbers given the rows and columns.
Practice question on GreatFrontEnd ->
How to solve it: Read rows and columns from the form, then build the table. The numbers run down the first column and back up the next one, like a snake. For each cell, check if the column index is even or odd to decide whether to count down or up.
Build a progress bar component that shows the percentage completion of an operation.
Practice question on GreatFrontEnd ->
How to solve it: Clamp the value between 0 and 100 and set the inner bar width to that percentage. Center the percentage text inside the filled portion and clip the fill to the rounded track. Add role="progressbar", an accessible name, and aria-valuenow, aria-valuemin, and aria-valuemax for screen readers.
Build a temperature converter widget that converts temperature values between Celsius and Fahrenheit.
Practice question on GreatFrontEnd ->
How to solve it: Keep Celsius and Fahrenheit as text values in state. When either input changes, preserve that typed value and update the other using F = C * 9 / 5 + 32 or C = (F - 32) * 5 / 9. Leave the converted field blank for empty or nonfinite input/results, and round converted values to four decimal places when necessary.
Build a component that resembles a Tweet from Twitter.
Practice question on GreatFrontEnd ->
How to solve it: Use flexbox to place the 48px rounded avatar beside the tweet body. Arrange the name, handle, date, message, and supplied action icons according to the specified spacing, colors, and font sizes. Give the body flex: 1 and min-width: 0 so text can wrap, and use justify-content: space-between for the action row. No state is needed.
Build a simple counter that increments whenever a button is clicked.
Practice question on GreatFrontEnd ->
How to solve it: Initialize the count to 0 with useState and display it inside the button. Increment with setCount(c => c + 1) on each click, using the previous state to calculate the next value. This is a short warm-up for the coding workspace.
Build a tabs component that displays a list of tab elements and one associated panel of content at a time.
Practice question on GreatFrontEnd ->
How to solve it: Store the active tab value in state, supporting an initial selection and defaulting to the first tab otherwise. Render buttons with an active visual style and show only the matching panel. Use stable tab values and keep state inside each component instance so multiple tab sets remain independent.
Build a users data table with pagination features.
Practice question on GreatFrontEnd ->
How to solve it: Keep the current page and page size in state, then slice the users array to get the rows for that page. Disable Prev on the first page and Next on the last. When the page size changes, reset to page 1 so you never land on an empty page.
Build a dice roller app that simulates the results of rolling 6-sided dice.
Practice question on GreatFrontEnd ->
How to solve it: Validate that the dice count is an integer from 1 to 12. On Roll, generate that many values with Math.floor(Math.random() * 6) + 1 and store them in state. Render the dice in rows of three, drawing each face with a small CSS grid of dots.
Build a file explorer component to navigate files and directories in a tree-like hierarchical viewer.
Practice question on GreatFrontEnd ->
How to solve it: Render the tree recursively, distinguishing folders by the presence of children, including empty arrays. Keep each folder's expanded state local, indent its children, and leave files noninteractive. Sort a copy of each sibling list with folders first, then alphabetically within each category.
Build a Like button that changes appearance based on the states.
Practice question on GreatFrontEnd ->
How to solve it: Track liked, loading, and error states. POST JSON with action: "like" or "unlike" to the provided API, and change the liked state only when the HTTP response succeeds. Disable repeat clicks while loading, then show any server or network error below the button. Keep the label "Like" and reflect the selection with aria-pressed.
Build a reusable modal dialog component that can be opened and closed.
Practice question on GreatFrontEnd ->
How to solve it: Accept open, title, children, and onClose as props, returning nothing when closed. Use createPortal to render a viewport overlay and centered dialog into document.body, with the title, body, and a close button. Implement this exercise without the native dialog element; the later versions add ARIA and focus behavior.
Build a star rating component that shows a row of star icons for users to select the number of filled stars corresponding to the rating.
Practice question on GreatFrontEnd ->
How to solve it: Render the max number of stars and fill those up to the current value. Keep a hovered index in state so hovering previews the rating, and clear it on mouse leave. Clicking a star calls onChange with that number.
Build a Todo list that lets users add new tasks and delete existing tasks.
Practice question on GreatFrontEnd ->
How to solve it: Store tasks as objects with stable ids and labels, alongside the input text. On Submit, trim the input, ignore empty additions, append a new task, and clear the field. Render task labels as plain React text and delete by filtering on id. Give the input an accessible label and use task ids as keys.
Build a traffic light where the lights switch from green to yellow to red after predetermined intervals and loop indefinitely.
Practice question on GreatFrontEnd ->
How to solve it: Use a configuration mapping each light to its duration and successor: green for 3000ms, yellow for 500ms, then red for 4000ms. Store the active light and schedule its successor with a timeout in useEffect, clearing it during cleanup. Announce the current light through a polite live status and hide decorative lights from assistive technology.
Build a 7-segment digital clock that shows the current time.
Practice question on GreatFrontEnd ->
How to solve it: Store the current Date in state, refresh it on an interval inside useEffect, and clear the interval on unmount. Pad hours, minutes, and seconds to two digits, then split each into its tens and units digits. Map each digit to the segments that should be lit and expose the readable time with a time element.
Build a tic-tac-toe game that is playable by two players.
Practice question on GreatFrontEnd ->
How to solve it: Keep the board as an array of 9 cells and work out whose turn it is from how many cells are filled. After each move, check the 8 winning lines. Block moves on filled cells or after a win, show a draw when the board is full, and add a reset.
Build an image carousel that displays a sequence of images.
Practice question on GreatFrontEnd ->
How to solve it: Store the current image index, starting at 0, and render only that image: this version permits just one image element in the DOM. Wrap Prev and Next with modulo arithmetic and add page buttons for direct navigation. Keep the whole image visible with object-fit: contain in a responsive carousel capped at 600px by 400px.
Build a job board that displays the latest job postings from Hacker News.
Practice question on GreatFrontEnd ->
How to solve it: Fetch the job ids from Hacker News, then fetch the first six item records in parallel while preserving their order. Load the next six on each Load more click, disabling the button during requests and hiding it once the ids are exhausted. Link titles when a URL exists and multiply API timestamps by 1000 before formatting them as dates.
Build a stopwatch widget that can measure how much time has passed.
Practice question on GreatFrontEnd ->
How to solve it: Keep the last tick timestamp in a ref and the accumulated duration in state. On each interval callback, add Date.now() - lastTick and update the ref; on Stop, add the remaining time since the last tick before clearing the interval. Format hours, minutes, seconds, and hundredths. Both the time button and Start/Stop toggle running; Reset stops and clears it. Clean up the interval on unmount.
Build a component that allows transferring of items between two lists.
Practice question on GreatFrontEnd ->
How to solve it: Keep each list as a Map from its unique item label to a checked flag. Clone the maps before changing selection or transferring items. The double arrows move all entries; the single arrows move only checked entries, appending them while preserving selection. Disable buttons with nothing to move, label each checkbox, and give arrow buttons descriptive accessible names.
Build an accessible accordion component that has the right ARIA roles, states, and properties.
Practice question on GreatFrontEnd ->
How to solve it: Build on Accordion and add the ARIA pieces. Each header button gets aria-expanded and aria-controls pointing at its panel, and each panel gets role="region" and aria-labelledby pointing back. Use useId to make the ids unique.
Build a fully accessible accordion component that has keyboard support according to ARIA specifications.
Practice question on GreatFrontEnd ->
How to solve it: Build on Accordion II and give header buttons unique ids. On Arrow Up/Down, find the current section and focus the adjacent header, wrapping at the ends; Home/End focus the first/last header. Prevent scrolling for handled keys. Keep all headers in the normal Tab sequence; native buttons handle Enter and Space.
Build an analog clock where the hands update and move like a real clock.
Practice question on GreatFrontEnd ->
How to solve it: Refresh the current Date on an interval and rotate the hands with CSS transforms. Use seconds * 6 for the second hand, (minutes + seconds / 60) * 6 for the minute hand, and ((hours % 12) + (minutes + seconds / 60) / 60) * 30 for the hour hand. Expose the time accessibly and clear the interval on unmount.
Build a users data table with sorting features.
Practice question on GreatFrontEnd ->
How to solve it: Store the sort column and direction. A new column sorts ascending and resets pagination to page 1; another click on the same column reverses the direction. Sort a copy of the complete dataset using localeCompare for strings and subtraction for numbers, then paginate that sorted result.
Build a semi-accessible file explorer component that has the right ARIA roles, states, and properties.
Practice question on GreatFrontEnd ->
How to solve it: Label the root tree, mark nodes as treeitem, and wrap each folder's children in a group. Apply aria-expanded to folders, leaving it off leaf files. Set aria-level from depth and calculate aria-setsize and aria-posinset within each sorted sibling group.
Build a file explorer component using a flat DOM structure.
Practice question on GreatFrontEnd ->
How to solve it: Keep recursive components, but have each return sibling list items inside React fragments instead of nesting another list. Render one outer list and indent each item according to its depth. Keep expanded state in each folder, rendering its descendant siblings only when open, and retain folder-first alphabetical sorting.
Build a grid of lights where the lights deactivate in the reverse order they were activated.
Practice question on GreatFrontEnd ->
How to solve it: Render the eight cells of a 3 by 3 grid with the center omitted. Track activated ids in click order, ignoring already active cells. Once all eight are on, remove the last id every 300ms until the list is empty. Ignore clicks during deactivation and clear the timer when finished or unmounted.
Build a semi-accessible modal dialog component that has the right ARIA roles, states, and properties.
Practice question on GreatFrontEnd ->
How to solve it: Add ARIA to the Modal Dialog. Give the container role="dialog" and aria-modal="true". Point aria-labelledby at the title and aria-describedby at the content, with ids from useId.
Build a moderately-accessible modal dialog component that supports common ways to close the dialog.
Practice question on GreatFrontEnd ->
How to solve it: Add the common ways to close it. Listen for the Escape key on the document while open, and remove the listener on close. Close on a click outside by checking the click didn't land inside the dialog, using a ref.
Build a list of progress bars that fill up gradually in sequence, one at a time.
Practice question on GreatFrontEnd ->
How to solve it: Append bars to a queue and let only the first unfinished bar animate from 0% to 100% over approximately 2000ms. On animation or transition completion, mark it finished and start the next queued bar. Newly added bars wait their turn.
Build a semi-accessible tabs component that has the right ARIA roles, states, and properties.
Practice question on GreatFrontEnd ->
How to solve it: Add ARIA to Tabs. The wrapper gets role="tablist", each button role="tab" with aria-selected and aria-controls, and each panel role="tabpanel" with aria-labelledby. Use useId for the ids.
Build a fully accessible tabs component that has keyboard support according to ARIA specifications.
Practice question on GreatFrontEnd ->
How to solve it: Keep refs to the tab buttons and use a roving tabIndex: 0 for the active tab and -1 for the others. Arrow Left/Right wrap focus, and Home/End move to the first/last tab. Activate each tab as it receives focus, as this exercise requires automatic activation. Prevent handled arrow keys from scrolling and make the panel keyboard-focusable when its content has no focusable element.
Build a list of progress bars that fill up gradually concurrently, up to a limit of 3.
Practice question on GreatFrontEnd ->
How to solve it: Track the total number of bars and the number completed. Start a bar when its index is less than completedCount + 3, giving it a 2000ms linear CSS transform transition. Increment the completion count on transitionend to open a slot for the next queued bar. Use a functional state update so simultaneous completions are counted correctly.
Build a widget that fetches birth year data from an API and plots it on a histogram.
Practice question on GreatFrontEnd ->
How to solve it: Fetch the random.org endpoint as text, split the newline-separated years, and count them into decade buckets using Math.floor(year / 10) * 10. Round the y-axis maximum up to a suitable count increment, then scale every bar against that same maximum. Label both axes, show loading/error states, and support Refresh with request cancellation.
Build a game for two players who take turns to drop colored discs from the top into a vertically suspended board/grid.
Practice question on GreatFrontEnd ->
How to solve it: Store a 6 by 7 grid and the active player. Drop each disc into the lowest empty row of the clicked column, ignoring full columns. Count matching discs in both directions along the horizontal, vertical, and two diagonal axes through the last move; four or more wins. Stop moves after a win or draw, show the status, and provide Restart.
Build an image carousel that smoothly transitions between images.
Practice question on GreatFrontEnd ->
How to solve it: Render all images in a horizontal strip inside a clipped viewport. Measure the carousel width and translate the strip by -currentIndex * imageWidth, adding a CSS transition only during navigation. Wrap navigation indices with modulo, ignore clicks while transitioning or on the active page, and clear the transition flag on transitionend. Recalculate the width on resize without animating the resize.
Build a counter with a history of the values and ability to undo/redo actions.
Practice question on GreatFrontEnd ->
How to solve it: Store the count and undo/redo stacks of actions with before and after values for /2, -1, +1, and x2. Render applied actions in the history table. Undo restores the previous value and moves the action to redo; Redo reapplies it. New operations clear redo, unavailable actions are disabled, and Reset clears the count and both stacks.
Build a signup form that validates user details and submits to a backend API.
Practice question on GreatFrontEnd ->
How to solve it: Validate an alphanumeric username of at least four characters, a reasonable email format, a password of at least six characters, and matching confirmation. Native constraints can cover most fields, with custom checking for the password match. Show errors next to their labeled inputs and associate custom messages with aria-describedby. Submit valid values through the supplied submitForm helper.
Build a memory game where the player needs to match pairs of cards.
Practice question on GreatFrontEnd ->
How to solve it: Shuffle pairs into an even-sized grid and track revealed and matched card ids. Ignore clicks on matched or already revealed cards. A matching pair stays visible; a mismatch flips back after a short delay or immediately when the player selects another card, which starts the next pair. Clear pending timeouts when the pair changes, and offer Play again after all pairs match.
Build a popular arcade game where players attempt to hit moles as they pop up from holes in a board.
Practice question on GreatFrontEnd ->
How to solve it: Keep configurable board and timing settings, defaulting to a 3 by 3 board, a 15-second round, one visible mole, and a 1500ms appearance interval. Start resets the score and timer and shows a random mole immediately. Replace visible positions at each appearance interval; a successful hit removes that mole and awards one point. At zero, stop the round and clear visible moles. Clean up both intervals.
Build a pixel art drawing tool where users can paint pixels with selected colors.
Practice question on GreatFrontEnd ->
How to solve it: Store a 15 by 15 grid of paint colors or null, the selected color, and Draw/Erase mode. Paint on left pointerdown and when entering cells during a drag; also handle clicks for keyboard activation. Erasing sets paint to null, revealing the CSS checkerboard. End dragging on window pointerup, pointercancel, or blur, and clean up those listeners.
Build a UI to filter, create, update, and delete users.
Practice question on GreatFrontEnd ->
How to solve it: Keep the client-side users array, search text, selected id, and first/last name fields in state. Filter immediately as search changes; selecting a user fills the form. Enable Create only with no selection and both names, Update with a selection and both names, and Delete/Cancel with a selection. Clear fields after Create or Cancel and remove stale selections after Delete.
Build a nested checkboxes component with parent-child selection logic.
Practice question on GreatFrontEnd ->
How to solve it: Update every descendant when a parent is toggled, then recompute ancestor states from the bottom up. A parent is checked when all children are checked, unchecked when all are unchecked, and indeterminate otherwise, including when a child is itself indeterminate. Set the native input's indeterminate DOM property through a ref, since it is not an HTML attribute.
Build an auth code input component that allows users to enter a 6-digit authorization code.
Practice question on GreatFrontEnd ->
How to solve it: Store six digit strings and input refs. Focus the first input initially; valid digits replace the current value and advance focus. Backspace clears a filled field, or moves back and clears it if empty; arrows move focus. Accept digit-only paste, replacing all fields from the first. POST the combined OTP to the provided endpoint, checking status without parsing the empty 204 success body. Disable controls during submission and provide Reset and result feedback.
Build a list of progress bars that fill up gradually concurrently, up to a limit of 3 and allows for pausing and resuming.
Practice question on GreatFrontEnd ->
How to solve it: Start paused with one empty bar and store each bar's percentage. Use one interval to increment the first three unfinished bars by 0.5 percentage points every 10ms, giving an approximate two-second fill. Pause clears the interval without changing progress; Start resumes it. Add preserves the running state, and Reset restores the initial paused bar. Stop the timer when all bars are full and clean it up on unmount.
Build a generalized data table with pagination and sorting features.
Practice question on GreatFrontEnd ->
How to solve it: Make the table generic. Pass in a columns config where each column has a key, a label, how to render the cell and how to compare two rows for sorting. The table handles sorting and pagination using only that config, so it works for any kind of data.
Build a fully-accessible modal dialog component that supports all required keyboard interactions.
Practice question on GreatFrontEnd ->
How to solve it: Save the invoking element before opening and move focus to the first focusable element inside the dialog. Trap Tab and Shift+Tab between its first and last tabbable elements, with a focusable dialog container as a fallback if none exist. Keep Escape and outside-click dismissal from the previous version, and restore focus to the invoking element on close.
Build an interface where users can drag to select multiple cells within a grid.
Practice question on GreatFrontEnd ->
How to solve it: Record the starting and current mouse coordinates on the page and draw a rectangle using their min/max bounds. Compare the rectangle's bounds with each cell's getBoundingClientRect() to highlight partial or full overlaps. Listen on the window so dragging works outside the grid. On release, hide the rectangle but retain highlights; a new left click clears the old selection. Disable text selection while dragging.
Build Wordle, the word-guessing game that took the world by storm.
Practice question on GreatFrontEnd ->
How to solve it: Choose a random provided word and track up to six guesses plus the current row. Handle letters, Backspace, and Enter from both physical and on-screen keyboards; Enter submits exactly five letters without dictionary validation. Score exact matches first, then other matches against remaining letter counts so duplicates score correctly. End on a correct guess or six attempts, then show Reset.
Build an N x N tic-tac-toe game that requires M consecutive marks to win.
Practice question on GreatFrontEnd ->
How to solve it: Store an N by N board as an array, the active player, and the winner. After each move, build the row, column, and two diagonals through that cell, scanning each for M consecutive identical nonempty marks. Reset the consecutive count when a cell is empty or the mark changes. Block occupied cells and moves after a win, show the turn/win/draw status, and provide Reset.
Build an image carousel that smoothly transitions between images that has a minimal DOM footprint.
Practice question on GreatFrontEnd ->
How to solve it: Render the current image and, during a transition, exactly one incoming image, keeping at most two image elements in the DOM. Position the incoming image on the appropriate side and animate both according to navigation direction, including wraparound. Remove the outgoing image when the transition ends, ignore overlapping navigation, and do nothing when the active page button is selected.
Build a component that allows transferring items between two lists, bulk selection/deselection of items, and adding new items.
Practice question on GreatFrontEnd ->
How to solve it: Build on Transfer List with a select-all checkbox and selected/total count per list. Derive checked and indeterminate states, disabling bulk selection for an empty list. Transfer selected items to the destination's bottom while preserving checked states. Add a labeled form to each list for new unique items, trimming text and ignoring empty additions. Keep checkbox and arrow controls keyboard-accessible.
Build a generalized data table with pagination, sorting and filtering features.
Practice question on GreatFrontEnd ->
How to solve it: Extend the generic column configuration with optional text or numeric-range filters. Match text case-insensitively, use inclusive min/max bounds for numbers, and ignore empty or invalid filter inputs. Keep only rows passing every active criterion, then sort and paginate that result. Reset or clamp the page when filters change and show an empty state when no rows match. Verify both supplied datasets.
If you found these 59 questions useful, you'll also like our Top ReactJS Interview Questions repository, a set of 50 React interview questions for further practice.