Build a Virtualized React Spreadsheet with Cell Formulas
HarveyFrontend Engineer · Technical ScreenLast updated
Design and implement a virtualized React spreadsheet component supporting editable cells, formula evaluation with string concatenation, cycle detection, and targeted re-rendering.
Task
Implement a performant React spreadsheet component (Spreadsheet) that renders a grid of cells (columns labeled A through Z, rows labeled 1 through N). The grid must support direct text entry, simple concatenation formulas referencing other cells, efficient virtualization for large row counts, and targeted re-renders.
Requirements
-
Formula Evaluation & References:
- A cell's raw input can be a literal string (e.g.,
Hello) or a formula beginning with=. - Support cell references and the string concatenation operator
&(e.g.,=A1 & " " & B1). - If a cell reference does not exist, evaluate it as
#REF!. - If a circular dependency is detected (e.g.,
A1referencesB1andB1referencesA1, or self-referenceA1 = =A1), evaluate affected cells as#CYCLE!.
- A cell's raw input can be a literal string (e.g.,
-
Virtualization:
- The grid must scale to 10,000 rows without rendering all DOM elements simultaneously.
- Given a container with fixed
heightandwidth, compute and render only visible rows/columns plus a configurable overscan buffer.
-
Re-render Optimization:
- Changing a cell's raw value must not cause all visible cells to re-render. Only the edited cell and cells directly or transitively dependent on it should re-evaluate and re-render.
Component Interface
interface SpreadsheetProps {
rowCount: number;
colCount: number; // 1 to 26 (A-Z)
cellWidth: number;
cellHeight: number;
viewportWidth: number;
viewportHeight: number;
overscan?: number; // default: 3
initialData?: Record; // e.g., { A1: "Hello", B1: "World", C1: "=A1 & \" \" & B1" }
}
export const Spreadsheet: React.FC = (props) => {
// Implementation
};
Example
Initial State:
A1="Hello"B1="World"C1="=A1 & \" \" & B1"D1="=C1 & \"!\""
Output Rendered Values:
A1:HelloB1:WorldC1:Hello WorldD1:Hello World!
Update:
- User edits
A1to"Hi". - Only cells
A1,C1, andD1re-evaluate.B1and all other cells remain untouched. C1evaluates toHi World,D1evaluates toHi World!.
Constraints
rowCount <= 50,000colCount <= 26(columnsAtoZ)- Formula tokens are limited to cell references (
[A-Z][1-9][0-9]*), string literals enclosed in double quotes ("..."), and the concatenation operator&.
Hints
Hint 1
Maintain a dependency graph (adjacency list of cell -> dependents) to determine which cells to recalculate and use cycle detection (DFS with visited states) during graph traversal.
Hint 2
For virtualization, track `scrollTop` in state or a ref, then calculate `startRow = Math.max(0, Math.floor(scrollTop / cellHeight) - overscan)` and `endRow` using the viewport height.
Hint 3
Separate raw input state from computed values, and wrap individual cell components in `React.memo` or use an external subscription store (e.g., Zustand/useSyncExternalStore) to isolate re-renders.
Follow-up questions
- How would you ensure full keyboard navigation (arrows, Tab, Enter) and screen reader accessibility (`aria-rowindex`, `role="grid"`) when rows scroll out of the virtualized DOM?
- How would you optimize bulk formula recalculations if a user pastes 1,000 cells at once to avoid deep recursion or UI thread freezing?
- How would you extend the dependency model to support collaborative multi-user editing with conflict-free replicated data types (CRDTs) or Operational Transformation (OT)?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.