Skip to content

Commit 4392e79

Browse files
authored
chore: adopt stable React Compiler lint rules (#4737)
1 parent ce40d02 commit 4392e79

108 files changed

Lines changed: 332 additions & 304 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.oxlintrc.json

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,19 @@
7070
"react/require-render-return": "error",
7171
"react/style-prop-object": "error",
7272
"react/void-dom-elements-no-children": "error",
73+
"react/error-boundaries": "off",
74+
"react/globals": "off",
75+
"react/immutability": "off",
76+
"react/incompatible-library": "off",
77+
"react/preserve-manual-memoization": "off",
78+
"react/purity": "off",
79+
"react/refs": "off",
80+
"react/set-state-in-effect": "off",
81+
"react/set-state-in-render": "off",
82+
"react/static-components": "off",
83+
"react/unsupported-syntax": "off",
84+
"react/use-memo": "off",
85+
"react/void-use-memo": "off",
7386
"react/checked-requires-onchange-or-readonly": "error",
7487
"react/forward-ref-uses-ref": "error",
7588
"react/iframe-missing-sandbox": "error",
@@ -124,7 +137,22 @@
124137
"react/button-has-type": "error",
125138
"react/jsx-no-useless-fragment": "error",
126139
"react/no-unstable-nested-components": "error",
127-
"react/react-compiler": "error",
140+
"react/error-boundaries": "error",
141+
"react/globals": "error",
142+
"react/hooks": "error",
143+
"react/immutability": "error",
144+
"react/incompatible-library": "error",
145+
"react/memo-dependencies": "error",
146+
"react/no-deriving-state-in-effects": "error",
147+
"react/preserve-manual-memoization": "error",
148+
"react/purity": "error",
149+
"react/refs": "error",
150+
"react/set-state-in-effect": "error",
151+
"react/set-state-in-render": "error",
152+
"react/static-components": "error",
153+
"react/unsupported-syntax": "error",
154+
"react/use-memo": "error",
155+
"react/void-use-memo": "error",
128156
"react/rules-of-hooks": "error",
129157
"trigger-runops/no-control-plane-run-graph-access": "error",
130158
"trigger-runops/no-control-plane-in-runops-slot": "error"
@@ -136,6 +164,12 @@
136164
"react/rules-of-hooks": "error"
137165
}
138166
},
167+
{
168+
"files": ["**/*.ts", "**/*.tsx"],
169+
"rules": {
170+
"no-redeclare": "off"
171+
}
172+
},
139173
{
140174
"files": ["apps/webapp/app/**/*.test.ts", "apps/webapp/app/**/*.test.tsx"],
141175
"rules": {

apps/webapp/app/components/AskAI.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ function ChatMessages({
273273
// Reset feedback state when conversation is reset
274274
useEffect(() => {
275275
if (conversation.length === 0) {
276-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
276+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
277277
setFeedbackGivenForQAs(new Set());
278278
}
279279
}, [conversation.length]);

apps/webapp/app/components/DevPresence.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export function DevPresenceProvider({ children, enabled = true }: DevPresencePro
5555
useEffect(() => {
5656
// If disabled or no events
5757
if (!enabled || streamedEvents === null) {
58-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
58+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
5959
setIsConnected(undefined);
6060
return;
6161
}
@@ -114,7 +114,7 @@ export function useCrossEngineIsConnected({
114114

115115
useEffect(() => {
116116
if (project.engine === "V2") {
117-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
117+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
118118
setCrossEngineIsConnected(isConnected);
119119
return;
120120
}

apps/webapp/app/components/Feedback.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export function Feedback({
7676
useEffect(() => {
7777
const open = searchParams.get("feedbackPanel");
7878
if (open) {
79-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
79+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
8080
setType(open as FeedbackType);
8181
setOpen(true);
8282
// Clone instead of mutating in place

apps/webapp/app/components/LoginPageLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export function LoginPageLayout({
4747
const [randomQuote, setRandomQuote] = useState<QuoteType | null>(null);
4848
useEffect(() => {
4949
const randomIndex = Math.floor(Math.random() * quotes.length);
50-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
50+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
5151
setRandomQuote(quotes[randomIndex]);
5252
}, []);
5353

apps/webapp/app/components/TriggerRotatingLogo.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export function TriggerRotatingLogo() {
2525
useEffect(() => {
2626
// Already registered from a previous render
2727
if (customElements.get("spline-viewer")) {
28-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
28+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
2929
setIsSplineReady(true);
3030
return;
3131
}

apps/webapp/app/components/admin/FeatureFlagsDialog.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export function FeatureFlagsDialog({
5656
const saveFetcher = useFetcher<ActionData>();
5757
const loadFeatureFlags = loadFetcher.load;
5858
const onOpenChangeRef = useRef(onOpenChange);
59-
// oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state.
59+
// oxlint-disable-next-line react/refs -- This ref intentionally coordinates an imperative integration outside React state.
6060
onOpenChangeRef.current = onOpenChange;
6161

6262
const [overrides, setOverrides] = useState<Record<string, unknown>>({});
@@ -68,7 +68,7 @@ export function FeatureFlagsDialog({
6868

6969
useEffect(() => {
7070
if (open && orgId) {
71-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
71+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
7272
setSaveError(null);
7373
setOverrides({});
7474
setInitialOverrides({});
@@ -79,7 +79,7 @@ export function FeatureFlagsDialog({
7979
useEffect(() => {
8080
if (loadFetcher.data) {
8181
const loaded = loadFetcher.data.orgFlags ?? {};
82-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
82+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
8383
setOverrides({ ...loaded });
8484
setInitialOverrides({ ...loaded });
8585
}
@@ -89,7 +89,7 @@ export function FeatureFlagsDialog({
8989
if (saveFetcher.data?.success) {
9090
onOpenChangeRef.current(false);
9191
} else if (saveFetcher.data?.error) {
92-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
92+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
9393
setSaveError(saveFetcher.data.error);
9494
}
9595
}, [saveFetcher.data]);

apps/webapp/app/components/admin/backOffice/MaxProjectsSection.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ export function MaxProjectsSection({
3434
const [value, setValue] = useState(String(maximumProjectCount));
3535

3636
useEffect(() => {
37-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
37+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
3838
if (hasFieldErrors) setIsEditing(true);
3939
}, [hasFieldErrors]);
4040

4141
useEffect(() => {
42-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
42+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
4343
if (savedJustNow && !hasFieldErrors) setIsEditing(false);
4444
}, [savedJustNow, hasFieldErrors]);
4545

apps/webapp/app/components/admin/backOffice/RateLimitSection.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ export function RateLimitSection({
6565
const [maxTokens, setMaxTokens] = useState(current ? String(current.maxTokens) : "");
6666

6767
useEffect(() => {
68-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
68+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
6969
if (hasFieldErrors) setIsEditing(true);
7070
}, [hasFieldErrors]);
7171

7272
useEffect(() => {
73-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
73+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
7474
if (savedJustNow && !hasFieldErrors) setIsEditing(false);
7575
}, [savedJustNow, hasFieldErrors]);
7676

apps/webapp/app/components/billing/BillingAlertsSection.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ export function BillingAlertsSection({
119119
return;
120120
}
121121

122-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
122+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
123123
setShowResetBanner(true);
124124

125125
if (searchParams.get("alertsReset") !== "1") {
@@ -141,12 +141,12 @@ export function BillingAlertsSection({
141141
);
142142
const maxAlerts = isPercentageMode ? MAX_PERCENTAGE_ALERTS : MAX_ABSOLUTE_ALERTS;
143143

144-
/* oxlint-disable react/react-compiler -- Stable derived thresholds prevent the synchronization effect from resetting local edits. */
144+
/* oxlint-disable react/preserve-manual-memoization -- Stable derived thresholds prevent the synchronization effect from resetting local edits. */
145145
const savedThresholds = useMemo(
146146
() => storedAlertsToThresholds(alerts, billingLimitMode, effectiveLimitCents, planLimitCents),
147147
[alerts, billingLimitMode, effectiveLimitCents, planLimitCents]
148148
);
149-
/* oxlint-enable react/react-compiler */
149+
/* oxlint-enable react/preserve-manual-memoization */
150150
const savedEmails = useMemo(() => alerts.emails, [alerts.emails]);
151151
const hasLegacySpikes = hasLegacySpikeAlertLevels(
152152
alerts,
@@ -190,7 +190,7 @@ export function BillingAlertsSection({
190190

191191
useEffect(() => {
192192
nextThresholdIdRef.current = savedThresholds.length;
193-
// oxlint-disable-next-line react/react-compiler -- This effect intentionally synchronizes local state after an external or lifecycle change.
193+
// oxlint-disable-next-line react/set-state-in-effect -- This effect intentionally synchronizes local state after an external or lifecycle change.
194194
setThresholdRows(toThresholdRows(savedThresholds));
195195
setEmailValues(savedEmails.length > 0 ? [...savedEmails, ""] : [""]);
196196
}, [savedThresholds, savedEmails]);

0 commit comments

Comments
 (0)