fix(core): add null checks for timeout refs and event listeners for React 19 compatibility (#9116)

## Description
- Add null checks before clearTimeout calls in colorful-fallback.tsx, edgeless.dialog.tsx, and local.dialog.tsx
- Fix event listener cleanup in unfolding.tsx
- Update tsconfig.jsx to use react-jsx transform

## Testing
- [x] Verified type safety improvements for React 19 compatibility
- [x] Ensured proper cleanup of event listeners and timeouts
- [x] Confirmed no unintended side effects from the changes

Link to Devin run: https://app.devin.ai/sessions/2e790f3ea0d84402837ec6c3c6f83e4c
This commit is contained in:
devin-ai-integration
2024-12-12 09:43:42 +00:00
parent dd39d049fe
commit e100d252b2
39 changed files with 496 additions and 368 deletions
@@ -27,7 +27,12 @@ import {
import { useService, WorkspaceService } from '@toeverything/infra';
import { cssVar } from '@toeverything/theme';
import { cssVarV2 } from '@toeverything/theme/v2';
import { type ReactElement, useCallback, useState } from 'react';
import {
type ReactElement,
type SVGAttributes,
useCallback,
useState,
} from 'react';
import * as style from './styles.css';
@@ -222,8 +227,8 @@ const ImportOptionItem = ({
onImport,
}: {
label: string;
prefixIcon: ReactElement;
suffixIcon?: ReactElement;
prefixIcon: ReactElement<SVGAttributes<SVGElement>>;
suffixIcon?: ReactElement<SVGAttributes<SVGElement>>;
suffixTooltip?: string;
type: ImportType;
onImport: (type: ImportType) => void;
@@ -4,7 +4,14 @@ import { SubscriptionPlan, SubscriptionRecurring } from '@affine/graphql';
import { Trans, useI18n } from '@affine/i18n';
import { AfFiNeIcon } from '@blocksuite/icons/rc';
import { useLiveData, useServices } from '@toeverything/infra';
import { type ReactNode, useEffect, useMemo, useRef, useState } from 'react';
import {
type ReactNode,
type RefObject,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { CloudPlanLayout } from './layout';
import { LifetimePlan } from './lifetime/lifetime-plan';
@@ -236,7 +243,7 @@ export const CloudPlans = () => {
// auto scroll to current plan card
useEffect(() => {
if (!scrollWrapper.current) return;
const currentPlanCard = scrollWrapper.current?.querySelector(
const currentPlanCard = scrollWrapper.current.querySelector(
'[data-current="true"]'
);
const wrapperComputedStyle = getComputedStyle(scrollWrapper.current);
@@ -247,11 +254,12 @@ export const CloudPlans = () => {
: 0;
const appeared = scrollWrapper.current.dataset.appeared === 'true';
const animationFrameId = requestAnimationFrame(() => {
scrollWrapper.current?.scrollTo({
if (!scrollWrapper.current) return;
scrollWrapper.current.scrollTo({
behavior: appeared ? 'smooth' : 'instant',
left,
});
scrollWrapper.current?.setAttribute('data-appeared', 'true');
scrollWrapper.current.dataset.appeared = 'true';
});
return () => {
cancelAnimationFrame(animationFrameId);
@@ -343,7 +351,7 @@ export const CloudPlans = () => {
select={cloudSelect}
toggle={cloudToggle}
scroll={cloudScroll}
scrollRef={scrollWrapper}
scrollRef={scrollWrapper as RefObject<HTMLDivElement>}
lifetime={isOnetimePro ? null : <LifetimePlan />}
/>
);