Add DOM fixture page for Fragment Ref (#32527)
This adds a page to the DOM fixture to test Fragment Refs. The first test case is for `addEventListener`/`removeEventListener`. Setting `enableFragmentRefs` to `__EXPERIMENTAL__` and building is required to run the fixture. <img width="872" alt="Screenshot 2025-03-05 at 12 58 57 PM" src="https://github.com/user-attachments/assets/fee498b7-fd96-4178-9e82-c46d4cb55c9b" />
Jack Pope committed
Mar 12, 2025 at 17:49 UTC
5135f98795d13aeea6f009b537a660c7afbe17ed
3 files changed
+118
fixtures/dom/src/components/Header.js
+1
@@ -89,6 +89,7 @@ class Header extends React.Component {
89
<option value="/selection-events">Selection Events</option>
90
<option value="/suspense">Suspense</option>
91
<option value="/form-state">Form State</option>
92
+ <option value="/fragment-refs">Fragment Refs</option>
93
</select>
94
</label>
95
<label htmlFor="global_version">
fixtures/dom/src/components/fixtures/fragment-refs/index.js
new
+104
@@ -0,0 +1,104 @@
1
+import Fixture from '../../Fixture';
2
+import FixtureSet from '../../FixtureSet';
3
+import TestCase from '../../TestCase';
4
+
5
+const React = window.React;
6
+const {Fragment, useEffect, useRef, useState} = React;
7
+
8
+function WrapperComponent(props) {
9
+ return props.children;
10
+}
11
+
12
+function handler(e) {
13
+ const text = e.currentTarget.innerText;
14
+ alert('You clicked: ' + text);
15
+}
16
+
17
+export default function FragmentRefsPage() {
18
+ const fragmentRef = useRef(null);
19
+ const [extraChildCount, setExtraChildCount] = useState(0);
20
+
21
+ React.useEffect(() => {
22
+ fragmentRef.current.addEventListener('click', handler);
23
+
24
+ const lastFragmentRefValue = fragmentRef.current;
25
+ return () => {
26
+ lastFragmentRefValue.removeEventListener('click', handler);
27
+ };
28
+ });
29
+
30
+ return (
31
+ <FixtureSet title="Fragment Refs">
32
+ <TestCase title="Event registration">
33
+ <TestCase.Steps>
34
+ <li>Click one of the children, observe the alert</li>
35
+ <li>Add a new child, click it, observe the alert</li>
36
+ <li>Remove the event listeners, click a child, observe no alert</li>
37
+ <li>
38
+ Add the event listeners back, click a child, observe the alert
39
+ </li>
40
+ </TestCase.Steps>
41
+
42
+ <TestCase.ExpectedResult>
43
+ <p>
44
+ Fragment refs can manage event listeners on the first level of host
45
+ children. This page loads with an effect that sets up click event
46
+ hanndlers on each child card. Clicking on a card will show an alert
47
+ with the card's text.
48
+ </p>
49
+ <p>
50
+ New child nodes will also have event listeners applied. Removed
51
+ nodes will have their listeners cleaned up.
52
+ </p>
53
+ </TestCase.ExpectedResult>
54
+
55
+ <Fixture>
56
+ <div className="control-box" id="control-box">
57
+ <div>Target count: {extraChildCount + 3}</div>
58
+ <button
59
+ onClick={() => {
60
+ setExtraChildCount(prev => prev + 1);
61
+ }}>
62
+ Add Child
63
+ </button>
64
+ <button
65
+ onClick={() => {
66
+ fragmentRef.current.addEventListener('click', handler);
67
+ }}>
68
+ Add click event listeners
69
+ </button>
70
+ <button
71
+ onClick={() => {
72
+ fragmentRef.current.removeEventListener('click', handler);
73
+ }}>
74
+ Remove click event listeners
75
+ </button>
76
+ <div class="card-container">
77
+ <Fragment ref={fragmentRef}>
78
+ <div className="card" id="child-a">
79
+ Child A
80
+ </div>
81
+ <div className="card" id="child-b">
82
+ Child B
83
+ </div>
84
+ <WrapperComponent>
85
+ <div className="card" id="child-c">
86
+ Child C
87
+ </div>
88
+ {Array.from({length: extraChildCount}).map((_, index) => (
89
+ <div
90
+ className="card"
91
+ id={'extra-child-' + index}
92
+ key={index}>
93
+ Extra Child {index}
94
+ </div>
95
+ ))}
96
+ </WrapperComponent>
97
+ </Fragment>
98
+ </div>
99
+ </div>
100
+ </Fixture>
101
+ </TestCase>
102
+ </FixtureSet>
103
+ );
104
+}
fixtures/dom/src/style.css
+13
@@ -309,3 +309,16 @@ th {
309
tbody tr:nth-child(even) {
310
background: #f0f0f0;
311
}
312
+
313
+.card-container {
314
+ display: flex;
315
+ flex-wrap: wrap;
316
+}
317
+
318
+.card {
319
+ background: white;
320
+ border-radius: 2px;
321
+ border: 1px solid rgba(0, 0, 0, 0.24);
322
+ margin: 10px;
323
+ padding: 10px;
324
+}