1
+
2
+## Input
3
+
4
+```javascript
5
+// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @loggerTestOnly @compilationMode:"infer"
6
+import {useState, useRef, useEffect, useEffectEvent} from 'react';
7
+
8
+function Component({x, y}) {
9
+ const previousXRef = useRef(null);
10
+ const previousYRef = useRef(null);
11
+
12
+ const [data, setData] = useState(null);
13
+
14
+ const effectEvent = useEffectEvent(() => {
15
+ const data = load({x, y});
16
+ setData(data);
17
+ });
18
+
19
+ useEffect(() => {
20
+ const previousX = previousXRef.current;
21
+ previousXRef.current = x;
22
+ const previousY = previousYRef.current;
23
+ previousYRef.current = y;
24
+ if (!areEqual(x, previousX) || !areEqual(y, previousY)) {
25
+ effectEvent();
26
+ }
27
+ }, [x, y]);
28
+
29
+ const effectEvent2 = useEffectEvent((xx, yy) => {
30
+ const previousX = previousXRef.current;
31
+ previousXRef.current = xx;
32
+ const previousY = previousYRef.current;
33
+ previousYRef.current = yy;
34
+ if (!areEqual(xx, previousX) || !areEqual(yy, previousY)) {
35
+ const data = load({x: xx, y: yy});
36
+ setData(data);
37
+ }
38
+ });
39
+
40
+ useEffect(() => {
41
+ effectEvent2(x, y);
42
+ }, [x, y]);
43
+
44
+ return data;
45
+}
46
+
47
+function areEqual(a, b) {
48
+ return a === b;
49
+}
50
+
51
+function load({x, y}) {
52
+ return x * y;
53
+}
54
+
55
+export const FIXTURE_ENTRYPOINT = {
56
+ fn: Component,
57
+ params: [{x: 0, y: 0}],
58
+ sequentialRenders: [
59
+ {x: 0, y: 0},
60
+ {x: 1, y: 0},
61
+ {x: 1, y: 1},
62
+ ],
63
+};
64
+
65
+```
66
+
67
+## Code
68
+
69
+```javascript
70
+import { c as _c } from "react/compiler-runtime"; // @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @loggerTestOnly @compilationMode:"infer"
71
+import { useState, useRef, useEffect, useEffectEvent } from "react";
72
+
73
+function Component(t0) {
74
+ const $ = _c(18);
75
+ const { x, y } = t0;
76
+ const previousXRef = useRef(null);
77
+ const previousYRef = useRef(null);
78
+
79
+ const [data, setData] = useState(null);
80
+ let t1;
81
+ if ($[0] !== x || $[1] !== y) {
82
+ t1 = () => {
83
+ const data_0 = load({ x, y });
84
+ setData(data_0);
85
+ };
86
+ $[0] = x;
87
+ $[1] = y;
88
+ $[2] = t1;
89
+ } else {
90
+ t1 = $[2];
91
+ }
92
+ const effectEvent = useEffectEvent(t1);
93
+ let t2;
94
+ if ($[3] !== effectEvent || $[4] !== x || $[5] !== y) {
95
+ t2 = () => {
96
+ const previousX = previousXRef.current;
97
+ previousXRef.current = x;
98
+ const previousY = previousYRef.current;
99
+ previousYRef.current = y;
100
+ if (!areEqual(x, previousX) || !areEqual(y, previousY)) {
101
+ effectEvent();
102
+ }
103
+ };
104
+ $[3] = effectEvent;
105
+ $[4] = x;
106
+ $[5] = y;
107
+ $[6] = t2;
108
+ } else {
109
+ t2 = $[6];
110
+ }
111
+ let t3;
112
+ if ($[7] !== x || $[8] !== y) {
113
+ t3 = [x, y];
114
+ $[7] = x;
115
+ $[8] = y;
116
+ $[9] = t3;
117
+ } else {
118
+ t3 = $[9];
119
+ }
120
+ useEffect(t2, t3);
121
+ let t4;
122
+ if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
123
+ t4 = (xx, yy) => {
124
+ const previousX_0 = previousXRef.current;
125
+ previousXRef.current = xx;
126
+ const previousY_0 = previousYRef.current;
127
+ previousYRef.current = yy;
128
+ if (!areEqual(xx, previousX_0) || !areEqual(yy, previousY_0)) {
129
+ const data_1 = load({ x: xx, y: yy });
130
+ setData(data_1);
131
+ }
132
+ };
133
+ $[10] = t4;
134
+ } else {
135
+ t4 = $[10];
136
+ }
137
+ const effectEvent2 = useEffectEvent(t4);
138
+ let t5;
139
+ if ($[11] !== effectEvent2 || $[12] !== x || $[13] !== y) {
140
+ t5 = () => {
141
+ effectEvent2(x, y);
142
+ };
143
+ $[11] = effectEvent2;
144
+ $[12] = x;
145
+ $[13] = y;
146
+ $[14] = t5;
147
+ } else {
148
+ t5 = $[14];
149
+ }
150
+ let t6;
151
+ if ($[15] !== x || $[16] !== y) {
152
+ t6 = [x, y];
153
+ $[15] = x;
154
+ $[16] = y;
155
+ $[17] = t6;
156
+ } else {
157
+ t6 = $[17];
158
+ }
159
+ useEffect(t5, t6);
160
+ return data;
161
+}
162
+
163
+function areEqual(a, b) {
164
+ return a === b;
165
+}
166
+
167
+function load({ x, y }) {
168
+ return x * y;
169
+}
170
+
171
+export const FIXTURE_ENTRYPOINT = {
172
+ fn: Component,
173
+ params: [{ x: 0, y: 0 }],
174
+ sequentialRenders: [
175
+ { x: 0, y: 0 },
176
+ { x: 1, y: 0 },
177
+ { x: 1, y: 1 },
178
+ ],
179
+};
180
+
181
+```
182
+
183
+## Logs
184
+
185
+```
186
+{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":179},"end":{"line":41,"column":1,"index":1116},"filename":"valid-setState-in-useEffect-via-useEffectEvent-with-ref.ts"},"fnName":"Component","memoSlots":18,"memoBlocks":6,"memoValues":6,"prunedMemoBlocks":0,"prunedMemoValues":0}
187
+```
188
+
189
+### Eval output
190
+(kind: ok) [[ (exception in render) TypeError: (0 , _react.useEffectEvent) is not a function ]]
191
+[[ (exception in render) TypeError: (0 , _react.useEffectEvent) is not a function ]]
192
+[[ (exception in render) TypeError: (0 , _react.useEffectEvent) is not a function ]]
\ No newline at end of file