React 19, Vite 7, Vitest 4 etc. (#2683)

This commit is contained in:
Kalle 2025-12-30 17:03:13 +02:00 committed by GitHub
parent 940b9f9706
commit 393955f5eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 225 additions and 756 deletions

View File

@ -8,6 +8,11 @@ import { useIsMounted } from "~/hooks/useIsMounted";
import invariant from "~/utils/invariant";
import { SubmitButton } from "./SubmitButton";
interface ChildProps {
onPress?: () => void;
type?: "button";
}
export function FormWithConfirm({
fields,
children,
@ -22,7 +27,7 @@ export function FormWithConfirm({
| [name: string, value: string | number]
| readonly [name: string, value: string | number]
)[];
children: React.ReactNode;
children: React.ReactElement<ChildProps>;
dialogHeading: string;
submitButtonText?: string;
action?: string;

View File

@ -1,4 +1,5 @@
import clsx from "clsx";
import type { JSX } from "react";
import * as React from "react";
import {
Button as ReactAriaButton,

View File

@ -27,7 +27,7 @@ export function SendouForm<T extends z.ZodTypeAny>({
const { t } = useTranslation(["common"]);
const fetcher = useFetcher<any>();
const methods = useForm({
resolver: standardSchemaResolver(schema),
resolver: standardSchemaResolver(schema as any),
defaultValues,
});

View File

@ -14,7 +14,7 @@ const THRESHOLD = 100;
export function useChatAutoScroll(
messages: ChatMessage[],
ref: React.RefObject<HTMLOListElement>,
ref: React.RefObject<HTMLOListElement | null>,
) {
const user = useUser();
const [firstLoadHandled, setFirstLoadHandled] = React.useState(false);
@ -94,7 +94,7 @@ export function useChat({
connected?: boolean;
}) {
const { revalidate } = useRevalidator();
const shouldRevalidate = React.useRef<boolean>();
const shouldRevalidate = React.useRef<boolean>(undefined);
const user = useUser();
const [messages, setMessages] = React.useState<ChatMessage[]>([]);
@ -106,7 +106,7 @@ export function useChat({
rooms[0]?.code,
);
const ws = React.useRef<WebSocket>();
const ws = React.useRef<WebSocket>(undefined);
const lastSeenMessagesByRoomId = React.useRef<Map<string, string>>(new Map());
// same principal as here behind separating it into a ref: https://overreacted.io/making-setinterval-declarative-with-react-hooks/

View File

@ -1,5 +1,5 @@
import clsx from "clsx";
import React from "react";
import React, { type JSX } from "react";
import { useTranslation } from "react-i18next";
import type { ShouldRevalidateFunction } from "react-router";
import { Ability } from "~/components/Ability";

View File

@ -1,3 +1,4 @@
import type { JSX } from "react";
import { useFetcher } from "react-router";
import { InfoPopover } from "~/components/InfoPopover";
import { LockIcon } from "~/components/icons/Lock";

View File

@ -1,6 +1,7 @@
import clsx from "clsx";
import { differenceInMinutes } from "date-fns";
import type { TFunction } from "i18next";
import type { JSX } from "react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Form, useLoaderData } from "react-router";

View File

@ -6,7 +6,7 @@ import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";
function useEventListener<K extends keyof MediaQueryListEventMap>(
eventName: K,
handler: (event: MediaQueryListEventMap[K]) => void,
element: RefObject<MediaQueryList>,
element: RefObject<MediaQueryList | null>,
options?: boolean | AddEventListenerOptions,
): void;
@ -25,7 +25,7 @@ function useEventListener<
>(
eventName: K,
handler: (event: HTMLElementEventMap[K]) => void,
element: RefObject<T>,
element: RefObject<T | null>,
options?: boolean | AddEventListenerOptions,
): void;
@ -33,7 +33,7 @@ function useEventListener<
function useEventListener<K extends keyof DocumentEventMap>(
eventName: K,
handler: (event: DocumentEventMap[K]) => void,
element: RefObject<Document>,
element: RefObject<Document | null>,
options?: boolean | AddEventListenerOptions,
): void;
@ -51,7 +51,7 @@ function useEventListener<
| MediaQueryListEventMap[KM]
| Event,
) => void,
element?: RefObject<T>,
element?: RefObject<T | null>,
options?: boolean | AddEventListenerOptions,
) {
// Create a ref that stores handler

View File

@ -1,4 +1,4 @@
import React from "react";
import React, { type JSX } from "react";
interface MasonryProps {
children: React.ReactNode | React.ReactNode[];
@ -14,7 +14,7 @@ interface MasonryProps {
interface MasonryState {
columns: React.ReactNode[][];
childRefs: React.RefObject<HTMLDivElement>[];
childRefs: React.RefObject<HTMLDivElement | null>[];
hasDistributed: boolean;
children?: React.ReactNode | React.ReactNode[];
}
@ -101,7 +101,7 @@ class Masonry extends React.Component<MasonryProps, MasonryState> {
() => [],
);
let validIndex = 0;
const childRefs: React.RefObject<HTMLDivElement>[] = [];
const childRefs: React.RefObject<HTMLDivElement | null>[] = [];
React.Children.forEach(children, (child) => {
if (child && React.isValidElement(child)) {
const ref = React.createRef<HTMLDivElement>();

View File

@ -24,7 +24,7 @@ const MasonryResponsive = ({
return (
<div>
{React.Children.map(children, (child, index) =>
React.cloneElement(child as React.ReactElement, {
React.cloneElement(child as React.ReactElement<any>, {
key: index,
columnsCount,
}),

View File

@ -5,10 +5,7 @@
"type": true
},
"tags": ["-lintignore"],
"ignoreDependencies": [
"react-compiler-runtime",
"babel-plugin-react-compiler"
],
"ignoreDependencies": ["babel-plugin-react-compiler"],
"entry": [
"app/features/*/routes/**/*.{ts,tsx}",
"migrations/**/*.js",

913
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -69,19 +69,18 @@
"openskill": "^4.1.0",
"p-limit": "^7.2.0",
"partysocket": "^1.1.10",
"react": "^18.3.1",
"react": "^19.2.3",
"react-aria-components": "^1.14.0",
"react-charts": "^3.0.0-beta.57",
"react-compiler-runtime": "^19.1.0-rc.2",
"react-dom": "^18.3.1",
"react-error-boundary": "^6.0.0",
"react-dom": "^19.2.3",
"react-error-boundary": "^6.0.1",
"react-flip-toolkit": "7.2.4",
"react-hook-form": "^7.69.0",
"react-i18next": "^16.5.0",
"react-router": "^7.11.0",
"react-use": "^17.6.0",
"react-use-draggable-scroll": "^0.4.7",
"remeda": "^2.32.0",
"remeda": "^2.32.1",
"remix-auth": "^4.2.0",
"remix-auth-oauth2": "^3.4.1",
"remix-i18next": "^7.4.2",
@ -99,22 +98,22 @@
"@types/node": "^25.0.3",
"@types/node-cron": "^3.0.11",
"@types/nprogress": "^0.2.3",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@types/web-push": "^3.6.4",
"babel-plugin-react-compiler": "^19.1.0-rc.2",
"cross-env": "^10.1.0",
"dotenv": "^17.2.3",
"i18next-locales-sync": "^2.1.1",
"knip": "^5.77.4",
"knip": "^5.78.0",
"ley": "^0.8.1",
"sql-formatter": "^15.6.12",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"vite": "^6.4.1",
"vite-node": "^3.2.4",
"vite": "^7.3.0",
"vite-node": "^5.2.0",
"vite-plugin-babel": "^1.3.2",
"vite-tsconfig-paths": "^6.0.3",
"vitest": "^3.2.4"
"vitest": "^4.0.16"
}
}

View File

@ -4,10 +4,6 @@ import babel from "vite-plugin-babel";
import tsconfigPaths from "vite-tsconfig-paths";
import { configDefaults } from "vitest/config";
const ReactCompilerConfig = {
target: "18",
};
export default defineConfig(() => {
return {
ssr: {
@ -24,7 +20,7 @@ export default defineConfig(() => {
filter: /\.[jt]sx?$/,
babelConfig: {
presets: ["@babel/preset-typescript"],
plugins: [["babel-plugin-react-compiler", ReactCompilerConfig]],
plugins: [["babel-plugin-react-compiler", {}]],
},
}),
tsconfigPaths(),