Source-linked AI summary
Refactoring React Component Hierarchies to Eliminate Prop Drilling
Vangelis Gkinis, Vassilis E. Zafeiris
TL;DR
Prop Drilling is discouraged, yet its prevalence, complexity, and potential for automated refactoring have been little studied. This paper uses static analysis to identify instances and automate refactorings through the Context API and Component Composition. On a benchmark of open-source React projects, it finds frequent occurrences and potential for automated elimination of 76.3% of prop drillings, primarily through the Context API.
Problem
Prop Drilling is discouraged and considered a code smell, but its prevalence, complexity, and potential for automated refactoring have received limited study.
Source: §1 · p. 3Method
Static analysis identifies Prop Drilling instances and applies automated refactorings based on the Context API and Component Composition.
Source: §1 · p. 3Results
76.3% of prop drillings could potentially be eliminated automatically, primarily through refactoring to the Context API.
Source: §1 · p. 3, §7 · p. 33Takeaways & Limitations
Prop drillings occur frequently across benchmark projects regardless of project size, with complexity more often involving simultaneous forwarding of multiple properties than propagation depth.
Source: §1 · p. 3The benchmark excludes closed-source projects, potentially limiting generalization to enterprise settings with different development practices and conventions.
Source: §6 · p. 32
Abstract
from arXiv · showhide
In React front-end development, Prop Drilling is the practice of propagating data through component properties across multiple levels of the component hierarchy. Despite being discouraged by React documentation and characterized as a code smell by recent research, little is known about its prevalence, complexity, and potential for automated refactoring. In this work, we propose a static analysis method for identifying Prop Drilling instances in a React codebase and eliminating them using two automated refactoring strategies based on Context API and Component Composition. The proposed method is implemented as a Node.js command line tool, ReactRefactor, and empirically evaluated on a benchmark dataset of open-source React applications. The main findings of the empirical evaluation indicate (a) the frequent occurrence of prop drillings across benchmark projects, irrespective of project size; (b) their generally low to moderate complexity in terms of data propagation depth, contrasted with the more prevalent complexity arising from the simultaneous forwarding of multiple properties along the same path; and, (c) the potential for automated elimination of a substantial share (76.3%) of prop drillings, primarily through refactoring to the Context API.
1. Introduction
Prop Drilling is discouraged because it can make forwarded values difficult to trace and tightly couple components. This paper presents static analysis and two automated refactoring strategies, then evaluates their prevalence, complexity, and refactoring potential on open-source React projects.
1. Introduction
- Prop Drilling forwards data through component properties across multiple hierarchy levels, making forwarded values difficult to trace and participating components tightly coupled.React documentation advises avoiding it where possible in favor of alternatives such as the Context API.Source: §1 · p. 3
- The method identifies and eliminates Prop Drilling using static analysis and automated refactorings based on the Context API and Component Composition.The authors specify refactoring preconditions and source transformations; ReactRefactor implements the method and applies refactorings under user guidance.Source: §1 · p. 3
- 76.3% of prop drillings could potentially be eliminated automatically, primarily through refactoring to the Context API.The empirical study also found prop drillings across projects irrespective of size, generally low-to-moderate depth, and more frequent complexity from forwarding multiple properties along one path.Source: §1 · p. 3
- The paper contributes a static analysis method, an empirical study of Prop Drilling prevalence and complexity, and the open-source ReactRefactor implementation.The authors describe this as the first work to study automation of large-scale refactoring in a React codebase, to their knowledge.Source: §1 · p. 3
2. Related Work
Prior work addresses JavaScript code smells and refactoring automation, while React-specific smell detection and refactoring research remains comparatively limited. This paper studies Prop Drilling and implements its identification and refactoring in ReactRefactor.
2. Related Work
- Prior JavaScript smell research covers broad catalogs and areas such as performance, server-side code, concurrency, security, and dependencies.Some studies also investigate smell prevalence, developer perceptions, or relationships with error-proneness and smell survival.Source: §2 · pp. 4–5
- React-specific prevalence research excluded Prop Drilling because ReactSniffer lacked sophisticated static analysis to detect it, and its authors planned to support detection in future versions.Ferreira and Valente proposed a catalog of 12 code smells and ReactSniffer; Nunes et al. later studied six TypeScript-related code smells with SniffTSX.Source: §2 · p. 5
- JavaScript refactoring automation spans static-analysis frameworks, data-flow-based transformations, and migrations to newer language features.The work most closely related to React automation describes seven operations but does not specify how to identify opportunities or the required transformations.Source: §2 · pp. 5–6
- This paper combines a study of Prop Drilling with static analysis and a fully implemented React refactoring, specifying preconditions to avoid unsafe suggestions and describing transformation steps.The authors characterize their work as the first study of a complex refactoring in React.Source: §2 · p. 6
3. The Prop Drilling Code Smell
The section introduces React-native alternatives to Prop Drilling and formalizes the component and property relationships used to describe it. A Carbon project example illustrates data passed from a top-level component to a deeply nested target.
3. The Prop Drilling Code Smell
- The Carbon example traces configuration data from the top-level Editor component to the deeply nested TitleBar through the component hierarchy.The section frames Context API and Component Composition as alternatives for propagating data across multiple hierarchy levels without Prop Drilling.Source: §3 · pp. 6–7
3.1. Core concepts and definitions
- Prop Forwarding assigns a child property the value of a parent property that is not defined in the parent component's implementation.A forwarding is pure when the source property is not referenced elsewhere in the parent implementation; the example's forwardings are pure.Source: §3.1 · p. 8
- A Prop Drilling is a sequence of prop passings from a source component to a different target component through intermediate participants.The sequence starts with a prop passing from the source and continues through forwardings; each forwarding must match the next property's source, and drilling ends when forwarding stops or changes the value.Source: §3.1 · pp. 8–9
- The depth metric counts intermediate components, equivalently the number of prop forwardings in a Prop Drilling instance.Its minimum is 1 because every instance includes at least one forwarding.Source: Prop Drilling Depth · p. 9
Prop Drilling Depth.
The number of properties forwarded along one path is a separate indicator of Prop Drilling coupling from its depth.
Prop Drilling Depth.
- A Compound Prop Drilling groups drillings that share a path and target properties in set J; its breadth is the number of properties in J.The passage introduces the set and its cardinality as the measure of breadth.Source: Compound Prop Drilling · p. 9
Compound Prop Drilling.
Compound Prop Drilling captures multiple properties forwarded along the same path, a pattern associated with stronger coupling. The paper describes Component Composition and the Context API as alternative refactoring strategies, with different effects on component structure and changes required.
Compound Prop Drilling.
- A Compound Prop Drilling groups drillings that share a source-to-target path; its breadth is the number of target properties forwarded.Greater breadth indicates stronger coupling, with more properties potentially requiring changes across the path.Source: Compound Prop Drilling · p. 9
- In the Carbon example, two Editor-to-TitleBar drillings have depth two and form a compound drilling of breadth two.A third drilling from Carbon can be included, yielding breadth three.Source: Compound Prop Drilling · pp. 9–10
3.2. Alternative Designs
- Adding a property to the Carbon-to-TitleBar compound drilling requires modifying three components, illustrating the path-wide coupling.The paper identifies difficulty tracing forwarded values and tight coupling as reasons Prop Drilling is treated as a code smell.Source: §3.2 · p. 10
- Component Composition pulls TitleBar markup up to Carbon, replaces WindowControls’ forwarded properties with children, and removes its dependency on TitleBar.WindowControls can then be extended with other components playing a similar role.Source: §3.2 · p. 10
- Composition may require all components along the drilling path to become composable, flattening the hierarchy and leaving only the source dependent on target and intermediate components.The source configures the nested target through prop passing.Source: §3.2 · p. 11
- The Context API makes a value available throughout a selected subtree, so components can access it directly rather than forwarding props.In the Carbon example, a provider wrapper accepts light, titleBar, and updateTitleBar; the involved passings and forwarded and target properties are removed, with the target consuming context through useContext().Source: §3.2 · p. 12
4. Elimination of Prop Drillings through refactoring
The paper presents a method to identify Prop Drilling instances in React codebases and eliminate them through automated refactoring.
4. Elimination of Prop Drillings through refactoring
- The method identifies Prop Drilling instances in a React codebase and eliminates them through automated refactoring.It recovers a graph representation of the codebase and uses graph traversal to identify drillings.Source: §4 · p. 13
- Refactoring preconditions determine whether a Prop Drilling instance is refactorable and whether Component Composition or the Context API applies.The method specifies source-code transformation procedures for either strategy.Source: §4 · p. 13
- The method specifies source-code transformations that eliminate a Prop Drilling instance using either strategy.The two strategies are Component Composition and the Context API.Source: §4 · p. 13
4.1. Refactoring candidate identification procedure
The identification procedure recovers a Component Hierarchy Graph (CHG) through static analysis, then traverses it to locate Prop Drilling instances as refactoring candidates.
4.1. Refactoring candidate identification procedure
- All Prop Drilling instances are treated as refactoring candidates, identified using a CHG that captures component dependencies and prop passings and forwardings.The CHG is recovered from the codebase as the first stage of refactoring automation.Source: §4.1 · p. 13
4.1.1. Component Hierarchy Graph construction
- The CHG statically analyzes production JS/TS files to represent components, parent-child dependencies, and prop passings and forwardings, approximating the codebase.The approximation reflects dynamic JS/TS features that hinder precise component and alias identification.Source: §4.1.1 · pp. 13, 15
- The method recognizes classes extending React Component or PureComponent and functions returning JSX as components.Capitalized names and function-initialized variable declarations are also part of its identification checks.Source: §4.1.1 · pp. 14–15
- Component identification extracts each component’s fully qualified name, properties, and JSX component uses, including their property assignments.The method supports function and class declarations, arrow functions, and function expressions, while assuming practices recommended by React documentation.Source: §4.1.1 · pp. 14–15
4.1.2. Resolution of Prop Forwardings
- For each component use, the method records an edge between parent and child and resolves prop assignments into passings or forwardings.A simple variable expression referring to a parent property can be classified as forwarding; constants and complex expressions are passings.Source: §4.1.1 · p. 16, §4.1.2 · p. 17
4.1.3. Identification of Prop Drilling instances
- Identification starts from application roots and follows compatible prop-forwarding sequences across CHG edges to find drillings.Roots may be inferred from code-layout conventions, supplied by the user, or—in an exhaustive search—include components without incoming edges.Source: §4.1.3 · pp. 17–18
- A forwarding path is at least two edges long, with forwardings on every edge except possibly its first; a drilling requires at least two prop passings or forwardings in sequence.The traversal matches each passing’s property name against forwardings on successive edges and records a drilling when the match sequence ends.Source: §4.1.3 · pp. 18–19
4.2. Source Code Transformation Procedure
The procedure tests whether a prop-drilling instance is safe to refactor, then applies either Component Composition or the Context API. Composition replaces forwarding with nested children; Context makes values available through a provider and consumer components.
4.2.1. Refactoring Preconditions
- If Component Composition preconditions fail, the method tests Context API preconditions; it rejects the instance if those also fail.The checks are intended to prevent syntax errors or changes to external behavior.Source: §4.2 · p. 20
4.2.2. Refactoring to Component Composition
- Composition nests the target along the component path, passes needed values to the relevant components, and replaces forwarded properties with the reserved children property.Intermediate components must not use children elsewhere, and the target component is not modified.Source: §4.2.2 · pp. 21–23
4.2.3. Refactoring to Context API
- For Context API refactoring, an adapter wraps Context.Provider so it can receive multiple properties, then exposes those values to the component subtree.The source component's property assignments move to the adapter, while participant components remove forwarded properties and read needed values from context.Source: §4.2.3 · pp. 23–25
- The Context API transformation simplifies participant component specifications by removing forwarded properties; the adapter preserves access to their values.The procedure creates and exports a Context object and provider adapter, then updates the source and participant components.Source: §4.2.3 · pp. 23–25
5. Empirical evaluation
The study evaluates ReactRefactor on 15 open-source React projects, examining Prop Drilling prevalence, complexity, and automated refactoring applicability. Most identified instances are refactorable, with Context API refactoring applicable to a broad share.
5. Empirical evaluation
- The evaluation uses 15 open-source React projects and the ReactRefactor command-line tool, which identifies candidates and lets users select an applicable refactoring strategy.The dataset excludes four component libraries because their internal structures differ substantially from typical React applications.Source: §5 · p. 25, §5.2 · pp. 26–27
5.3.1. RQ1. How common are Prop Drilling occurrences in real-world React applications?
- 10 of 15 projects contain at least 50 Prop Drillings, three of the largest contain more than 1,000, and participants comprise at least 25% of components in 10 projects.Pure Prop Drillings range from 28% to 95% of project instances, with a median of 46.6%.Source: §5.3.1 · pp. 27–28, Table 2 · p. 28
5.3.2. RQ2. What is the range of Prop Drilling complexity?
- 77.2% of Prop Drillings and 87.7% of pure Prop Drillings have depth 1, while 54.9% of all Prop Drillings participate in compound drillings and 28.3% are members of compounds with breadth ≥3.The authors characterize depth as generally low, while simultaneous forwarding of multiple properties is more prevalent.Source: Figure 10 · p. 29, §5.3.2 · pp. 29–30, Table 3 · p. 30
5.3.3. RQ3. What ratio of Prop Drillings can be eliminated through fully automated refactoring?
- 76.3% of all Prop Drillings and 73.6% of pure Prop Drillings can be refactored through at least one strategy; Context API applies to 74.9% and 71.6%, respectively.Component Composition applies to 7.3% of all Prop Drillings and 4.8% of pure Prop Drillings; some instances qualify for both strategies.Source: Figure 11 · p. 31, §5.3.3 · p. 31
6. Threats to validity
The study discusses threats to internal, external, construct, and conclusion validity, along with steps taken to mitigate them. The benchmark’s exclusion of closed-source projects limits how directly the findings generalize to enterprise settings.
Internal validity
- The benchmark’s project selection may be biased, though it includes all projects used in relevant empirical studies published in top-tier journals.The study is exploratory and does not seek to confirm a causal relationship.Source: §6 · p. 32
External validity
- Closed-source projects are absent, potentially limiting generalization to enterprise settings with different development practices and conventions.The authors trade off this aspect of external validity in favor of reproducibility and transparency.Source: §6 · p. 32
Construct validity
- Implementation bugs could cause missed prop drillings or false positives; manual inspection of several cases and a basic test suite partly mitigate this threat.The threat concerns whether the theoretical constructs correspond to the evaluation observations.Source: §6 · p. 32
Conclusion validity
- Because the study is exploratory, the authors assess reliability rather than statistical significance of causal hypotheses; reproducibility is a concern.They alleviate that concern by releasing ReactRefactor and replication artifacts in a Zenodo archive.Source: §6 · pp. 32–33
7. Conclusions – Future Work
The paper presents static analysis and two React-native refactoring strategies for identifying and eliminating prop drillings. In 15 open-source projects, 76.3% were refactorable, with the Context API applicable to most instances.
Conclusions
- 76.3% of prop drillings were refactorable; the Context API strategy applied to 74.9% and Component Composition to 7.3% of all instances.The method uses a Component Hierarchy Graph, a traversal algorithm, refactoring preconditions, and source-code transformations.Source: §7 · p. 33
- Prop drillings occurred frequently across projects regardless of size, and about 20% had depth of at least 2, particularly in large projects.The depth of identified instances was generally low.Source: §7 · p. 33
- 54.9% of prop drillings participated in Compound Prop Drillings, making breadth complexity more prevalent than depth complexity.Source: §7 · p. 33
Future Work
- Future work could explore additional refactoring strategies, other tangled prop drillings, and generalization to frameworks such as Vue.js and Android Jetpack Compose.Source: §7 · p. 33