diff --git a/.changeset/purple-tables-switch.md b/.changeset/purple-tables-switch.md
new file mode 100644
index 00000000000..55d8f2650eb
--- /dev/null
+++ b/.changeset/purple-tables-switch.md
@@ -0,0 +1,8 @@
+---
+"@remix-run/dev": major
+"@remix-run/eslint-config": major
+"@remix-run/react": major
+"@remix-run/testing": major
+---
+
+Drop React 17 support
diff --git a/docs/guides/migrating-react-router-app.md b/docs/guides/migrating-react-router-app.md
index 47b1d05ed22..41384462f37 100644
--- a/docs/guides/migrating-react-router-app.md
+++ b/docs/guides/migrating-react-router-app.md
@@ -166,16 +166,7 @@ function handleBrowserRequest(
}
```
-If you are using React 17, your client entrypoint will look like this:
-
-```tsx filename=app/entry.client.tsx lines=[2,4]
-import { RemixBrowser } from "@remix-run/react";
-import { hydrate } from "react-dom";
-
-hydrate(, document);
-```
-
-In React 18, you'll use `hydrateRoot` instead of `hydrate`.
+Your client entrypoint will look like this:
```tsx filename=app/entry.client.tsx
import { RemixBrowser } from "@remix-run/react";
diff --git a/docs/guides/typescript.md b/docs/guides/typescript.md
index 67243f439ef..c32cef4ecbf 100644
--- a/docs/guides/typescript.md
+++ b/docs/guides/typescript.md
@@ -24,14 +24,14 @@ The Remix compiler will not do any type checking (it simply removes the types).
"@remix-run/node": "latest",
"@remix-run/react": "latest",
"@remix-run/serve": "latest",
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
},
"devDependencies": {
"@remix-run/dev": "latest",
"@remix-run/eslint-config": "latest",
- "@types/react": "^17.0.38",
- "@types/react-dom": "^17.0.11",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"eslint": "^8.23.1",
"typescript": "^5.1.6"
},
diff --git a/integration/server-entry-test.ts b/integration/server-entry-test.ts
index 5d23a6acdcb..5e593306521 100644
--- a/integration/server-entry-test.ts
+++ b/integration/server-entry-test.ts
@@ -1,6 +1,6 @@
import { test, expect } from "@playwright/test";
-import { createFixture, js, json } from "./helpers/create-fixture.js";
+import { createFixture, js } from "./helpers/create-fixture.js";
import type { Fixture } from "./helpers/create-fixture.js";
import { selectHtml } from "./helpers/playwright-fixture.js";
@@ -62,54 +62,3 @@ test.describe("Default Server Entry", () => {
expect(selectHtml(await response.text(), "p")).toBe("
Hello World
");
});
});
-
-test.describe("Default Server Entry (React 17)", () => {
- let fixture: Fixture;
-
- test.beforeAll(async () => {
- fixture = await createFixture({
- files: {
- "app/routes/_index.tsx": js`
- export default function () {
- return Hello World
- }
- `,
- "package.json": json({
- name: "remix-template-remix",
- private: true,
- sideEffects: false,
- type: "module",
- scripts: {
- build:
- "node ../../../build/node_modules/@remix-run/dev/dist/cli.js build",
- dev: "node ../../../build/node_modules/@remix-run/dev/dist/cli.js dev",
- start:
- "node ../../../build/node_modules/@remix-run/serve/dist/cli.js build",
- },
- dependencies: {
- "@remix-run/node": "0.0.0-local-version",
- "@remix-run/react": "0.0.0-local-version",
- "@remix-run/serve": "0.0.0-local-version",
- isbot: "0.0.0-local-version",
- react: "17.0.2",
- "react-dom": "17.0.2",
- },
- devDependencies: {
- "@remix-run/dev": "0.0.0-local-version",
- "@types/react": "0.0.0-local-version",
- "@types/react-dom": "0.0.0-local-version",
- typescript: "0.0.0-local-version",
- },
- engines: {
- node: ">=18.0.0",
- },
- }),
- },
- });
- });
-
- test("renders", async () => {
- let response = await fixture.requestDocument("/");
- expect(selectHtml(await response.text(), "p")).toBe("Hello World
");
- });
-});
diff --git a/package.json b/package.json
index 99cbd738728..b895b422f02 100644
--- a/package.json
+++ b/package.json
@@ -77,8 +77,8 @@
"@types/jest": "^27.4.1",
"@types/jsonfile": "^6.1.0",
"@types/lodash": "^4.14.182",
- "@types/react": "^18.0.15",
- "@types/react-dom": "^18.0.6",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"@types/react-test-renderer": "^18.0.0",
"@types/retry": "^0.12.0",
"@types/semver": "^7.3.4",
diff --git a/packages/remix-dev/__tests__/fixtures/cloudflare/package.json b/packages/remix-dev/__tests__/fixtures/cloudflare/package.json
index deeb318a06e..ed124986811 100644
--- a/packages/remix-dev/__tests__/fixtures/cloudflare/package.json
+++ b/packages/remix-dev/__tests__/fixtures/cloudflare/package.json
@@ -23,8 +23,8 @@
"@cloudflare/workers-types": "^3.18.0",
"@remix-run/dev": "^1.12.0",
"@remix-run/eslint-config": "^1.12.0",
- "@types/react": "^18.0.25",
- "@types/react-dom": "^18.0.8",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"eslint": "^8.27.0",
"npm-run-all": "^4.1.5",
"typescript": "^5.1.6",
diff --git a/packages/remix-dev/__tests__/fixtures/deno/.vscode/resolve_npm_imports.json b/packages/remix-dev/__tests__/fixtures/deno/.vscode/resolve_npm_imports.json
index 5ef45c00688..a99a407595b 100644
--- a/packages/remix-dev/__tests__/fixtures/deno/.vscode/resolve_npm_imports.json
+++ b/packages/remix-dev/__tests__/fixtures/deno/.vscode/resolve_npm_imports.json
@@ -12,8 +12,8 @@
"@remix-run/server-runtime": "https://esm.sh/@remix-run/server-runtime@1.9.0",
"@remix-run/dev/server-build": "https://esm.sh/@remix-run/dev@1.9.0/server-build",
"@remix-run/react": "https://esm.sh/@remix-run/react@1.9.0",
- "react": "https://esm.sh/react@17.0.2",
- "react-dom": "https://esm.sh/react-dom@17.0.2",
- "react-dom/server": "https://esm.sh/react-dom@17.0.2/server"
+ "react": "https://esm.sh/react@18.2.0",
+ "react-dom": "https://esm.sh/react-dom@18.2.0",
+ "react-dom/server": "https://esm.sh/react-dom@18.2.0/server"
}
}
diff --git a/packages/remix-dev/__tests__/fixtures/indie-stack/package.json b/packages/remix-dev/__tests__/fixtures/indie-stack/package.json
index 226214cfcb7..459cee12fa4 100644
--- a/packages/remix-dev/__tests__/fixtures/indie-stack/package.json
+++ b/packages/remix-dev/__tests__/fixtures/indie-stack/package.json
@@ -14,8 +14,8 @@
"devDependencies": {
"@remix-run/dev": "*",
"@types/node": "^18.17.1",
- "@types/react": "^18.0.15",
- "@types/react-dom": "^18.0.6",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"typescript": "^5.1.6"
},
"engines": {
diff --git a/packages/remix-dev/__tests__/fixtures/node/package.json b/packages/remix-dev/__tests__/fixtures/node/package.json
index 024b859eeb9..65714ad2302 100644
--- a/packages/remix-dev/__tests__/fixtures/node/package.json
+++ b/packages/remix-dev/__tests__/fixtures/node/package.json
@@ -18,8 +18,8 @@
"devDependencies": {
"@remix-run/dev": "^1.12.0",
"@remix-run/eslint-config": "^1.12.0",
- "@types/react": "^18.0.25",
- "@types/react-dom": "^18.0.8",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"eslint": "^8.27.0",
"typescript": "^5.1.6"
},
diff --git a/packages/remix-dev/cli/commands.ts b/packages/remix-dev/cli/commands.ts
index 934d5bf9b5c..0f7fb771199 100644
--- a/packages/remix-dev/cli/commands.ts
+++ b/packages/remix-dev/cli/commands.ts
@@ -4,7 +4,6 @@ import fse from "fs-extra";
import getPort, { makeRange } from "get-port";
import prettyMs from "pretty-ms";
import NPMCliPackageJson from "@npmcli/package-json";
-import { coerce } from "semver";
import pc from "picocolors";
import * as colors from "../colors";
@@ -214,20 +213,6 @@ export async function generateEntry(
let pkgJson = await NPMCliPackageJson.load(config.rootDirectory);
let deps = pkgJson.content.dependencies ?? {};
- let maybeReactVersion = coerce(deps.react);
- if (!maybeReactVersion) {
- let react = ["react", "react-dom"];
- let list = conjunctionListFormat.format(react);
- throw new Error(
- `Could not determine React version. Please install the following packages: ${list}`
- );
- }
-
- let type =
- maybeReactVersion.major >= 18 || maybeReactVersion.raw === "0.0.0"
- ? ("stream" as const)
- : ("string" as const);
-
let serverRuntime = deps["@remix-run/deno"]
? "deno"
: deps["@remix-run/cloudflare"]
@@ -251,26 +236,11 @@ export async function generateEntry(
return;
}
- let clientRenderer = deps["@remix-run/react"] ? "react" : undefined;
-
- if (!clientRenderer) {
- console.error(
- colors.error(
- `Could not determine runtime. Please install the following: @remix-run/react`
- )
- );
- return;
- }
-
let defaultsDirectory = path.resolve(__dirname, "..", "config", "defaults");
- let defaultEntryClient = path.resolve(
- defaultsDirectory,
- `entry.client.${clientRenderer}-${type}.tsx`
- );
+ let defaultEntryClient = path.resolve(defaultsDirectory, "entry.client.tsx");
let defaultEntryServer = path.resolve(
defaultsDirectory,
- serverRuntime,
- `entry.server.${clientRenderer}-${type}.tsx`
+ `entry.server.${serverRuntime}.tsx`
);
let isServerEntry = entry === "entry.server";
diff --git a/packages/remix-dev/config.ts b/packages/remix-dev/config.ts
index e4e6033c244..a54c293a1fa 100644
--- a/packages/remix-dev/config.ts
+++ b/packages/remix-dev/config.ts
@@ -3,7 +3,6 @@ import path from "node:path";
import { pathToFileURL } from "node:url";
import fse from "fs-extra";
import NPMCliPackageJson from "@npmcli/package-json";
-import { coerce } from "semver";
import type { NodePolyfillsOptions as EsbuildPluginsNodeModulesPolyfillOptions } from "esbuild-plugins-node-modules-polyfill";
import type { RouteManifest, DefineRoutesFunction } from "./config/routes";
@@ -419,7 +418,7 @@ export async function readConfig(
let userEntryServerFile = findEntry(appDirectory, "entry.server");
let entryServerFile: string;
- let entryClientFile: string;
+ let entryClientFile = userEntryClientFile || "entry.client.tsx";
let pkgJson = await NPMCliPackageJson.load(remixRoot);
let deps = pkgJson.content.dependencies ?? {};
@@ -447,29 +446,7 @@ export async function readConfig(
);
}
- let clientRenderer = deps["@remix-run/react"] ? "react" : undefined;
-
- if (!clientRenderer) {
- throw new Error(
- `Could not determine renderer. Please install the following: @remix-run/react`
- );
- }
-
- let maybeReactVersion = coerce(deps.react);
- if (!maybeReactVersion) {
- let react = ["react", "react-dom"];
- let list = conjunctionListFormat.format(react);
- throw new Error(
- `Could not determine React version. Please install the following packages: ${list}`
- );
- }
-
- let type: "stream" | "string" =
- maybeReactVersion.major >= 18 || maybeReactVersion.raw === "0.0.0"
- ? "stream"
- : "string";
-
- if (!deps["isbot"] && type === "stream") {
+ if (!deps["isbot"]) {
console.log(
"adding `isbot` to your package.json, you should commit this change"
);
@@ -491,35 +468,7 @@ export async function readConfig(
});
}
- entryServerFile = `${serverRuntime}/entry.server.${clientRenderer}-${type}.tsx`;
- }
-
- if (userEntryClientFile) {
- entryClientFile = userEntryClientFile;
- } else {
- let clientRenderer = deps["@remix-run/react"] ? "react" : undefined;
-
- if (!clientRenderer) {
- throw new Error(
- `Could not determine runtime. Please install the following: @remix-run/react`
- );
- }
-
- let maybeReactVersion = coerce(deps.react);
- if (!maybeReactVersion) {
- let react = ["react", "react-dom"];
- let list = conjunctionListFormat.format(react);
- throw new Error(
- `Could not determine React version. Please install the following packages: ${list}`
- );
- }
-
- let type: "stream" | "string" =
- maybeReactVersion.major >= 18 || maybeReactVersion.raw === "0.0.0"
- ? "stream"
- : "string";
-
- entryClientFile = `entry.client.${clientRenderer}-${type}.tsx`;
+ entryServerFile = `entry.server.${serverRuntime}.tsx`;
}
let entryClientFilePath = userEntryClientFile
@@ -712,11 +661,6 @@ declare namespace Intl {
}
}
-let conjunctionListFormat = new Intl.ListFormat("en", {
- style: "long",
- type: "conjunction",
-});
-
let disjunctionListFormat = new Intl.ListFormat("en", {
style: "long",
type: "disjunction",
diff --git a/packages/remix-dev/config/defaults/cloudflare/entry.server.react-string.tsx b/packages/remix-dev/config/defaults/cloudflare/entry.server.react-string.tsx
deleted file mode 100644
index a5b0fc4e06e..00000000000
--- a/packages/remix-dev/config/defaults/cloudflare/entry.server.react-string.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { AppLoadContext, EntryContext } from "@remix-run/cloudflare";
-import { RemixServer } from "@remix-run/react";
-import { renderToString } from "react-dom/server";
-
-export default function handleRequest(
- request: Request,
- responseStatusCode: number,
- responseHeaders: Headers,
- remixContext: EntryContext,
- loadContext: AppLoadContext
-) {
- let markup = renderToString(
-
- );
-
- responseHeaders.set("Content-Type", "text/html");
-
- return new Response("" + markup, {
- status: responseStatusCode,
- headers: responseHeaders,
- });
-}
diff --git a/packages/remix-dev/config/defaults/deno/entry.server.react-string.tsx b/packages/remix-dev/config/defaults/deno/entry.server.react-string.tsx
deleted file mode 100644
index 9aed20060bc..00000000000
--- a/packages/remix-dev/config/defaults/deno/entry.server.react-string.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { AppLoadContext, EntryContext } from "@remix-run/deno";
-import { RemixServer } from "@remix-run/react";
-import { renderToString } from "react-dom/server";
-
-export default function handleRequest(
- request: Request,
- responseStatusCode: number,
- responseHeaders: Headers,
- remixContext: EntryContext,
- loadContext: AppLoadContext
-) {
- let markup = renderToString(
-
- );
-
- responseHeaders.set("Content-Type", "text/html");
-
- return new Response("" + markup, {
- status: responseStatusCode,
- headers: responseHeaders,
- });
-}
diff --git a/packages/remix-dev/config/defaults/entry.client.react-string.tsx b/packages/remix-dev/config/defaults/entry.client.react-string.tsx
deleted file mode 100644
index 3eec1fd0a02..00000000000
--- a/packages/remix-dev/config/defaults/entry.client.react-string.tsx
+++ /dev/null
@@ -1,4 +0,0 @@
-import { RemixBrowser } from "@remix-run/react";
-import { hydrate } from "react-dom";
-
-hydrate(, document);
diff --git a/packages/remix-dev/config/defaults/entry.client.react-stream.tsx b/packages/remix-dev/config/defaults/entry.client.tsx
similarity index 100%
rename from packages/remix-dev/config/defaults/entry.client.react-stream.tsx
rename to packages/remix-dev/config/defaults/entry.client.tsx
diff --git a/packages/remix-dev/config/defaults/cloudflare/entry.server.react-stream.tsx b/packages/remix-dev/config/defaults/entry.server.cloudflare.tsx
similarity index 100%
rename from packages/remix-dev/config/defaults/cloudflare/entry.server.react-stream.tsx
rename to packages/remix-dev/config/defaults/entry.server.cloudflare.tsx
diff --git a/packages/remix-dev/config/defaults/deno/entry.server.react-stream.tsx b/packages/remix-dev/config/defaults/entry.server.deno.tsx
similarity index 100%
rename from packages/remix-dev/config/defaults/deno/entry.server.react-stream.tsx
rename to packages/remix-dev/config/defaults/entry.server.deno.tsx
diff --git a/packages/remix-dev/config/defaults/node/entry.server.react-stream.tsx b/packages/remix-dev/config/defaults/entry.server.node.tsx
similarity index 100%
rename from packages/remix-dev/config/defaults/node/entry.server.react-stream.tsx
rename to packages/remix-dev/config/defaults/entry.server.node.tsx
diff --git a/packages/remix-dev/config/defaults/node/entry.server.react-string.tsx b/packages/remix-dev/config/defaults/node/entry.server.react-string.tsx
deleted file mode 100644
index 29ede1fc5e1..00000000000
--- a/packages/remix-dev/config/defaults/node/entry.server.react-string.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { AppLoadContext, EntryContext } from "@remix-run/node";
-import { RemixServer } from "@remix-run/react";
-import { renderToString } from "react-dom/server";
-
-export default function handleRequest(
- request: Request,
- responseStatusCode: number,
- responseHeaders: Headers,
- remixContext: EntryContext,
- loadContext: AppLoadContext
-) {
- let markup = renderToString(
-
- );
-
- responseHeaders.set("Content-Type", "text/html");
-
- return new Response("" + markup, {
- status: responseStatusCode,
- headers: responseHeaders,
- });
-}
diff --git a/packages/remix-eslint-config/package.json b/packages/remix-eslint-config/package.json
index 256f8b1f38c..c8ba3302ac3 100644
--- a/packages/remix-eslint-config/package.json
+++ b/packages/remix-eslint-config/package.json
@@ -49,7 +49,7 @@
},
"peerDependencies": {
"eslint": "^8.0.0",
- "react": "^17.0.0 || ^18.0.0",
+ "react": "^18.0.0",
"typescript": "^5.1.0"
},
"peerDependenciesMeta": {
diff --git a/packages/remix-react/components.tsx b/packages/remix-react/components.tsx
index f5529272ee3..e14aed26339 100644
--- a/packages/remix-react/components.tsx
+++ b/packages/remix-react/components.tsx
@@ -231,7 +231,7 @@ function usePrefetchBehavior(
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
/**
- * A special kind of `` that knows whether or not it is "active".
+ * A special kind of `` that knows whether it is "active".
*
* @see https://remix.run/components/nav-link
*/
@@ -334,47 +334,19 @@ export function Links() {
return (
<>
- {keyedLinks.map(({ key, link }) => {
- if (isPageLinkDescriptor(link)) {
- return ;
- }
-
- let imageSrcSet: string | null = null;
- let imageSizes: string | null = null;
-
- // In React 17, and will warn
- // because the DOM attributes aren't recognized, so users need to pass
- // them in all lowercase to forward the attributes to the node without a
- // warning. Normalize so that either property can be used in Remix.
- let imageSizesKey = "useId" in React ? "imageSizes" : "imagesizes";
- let imageSrcSetKey = "useId" in React ? "imageSrcSet" : "imagesrcset";
- if (link.imageSrcSet) {
- imageSrcSet = link.imageSrcSet;
- delete link.imageSrcSet;
- }
-
- if (link.imageSizes) {
- imageSizes = link.imageSizes;
- delete link.imageSizes;
- }
-
- return (
-
- );
- })}
+ {keyedLinks.map(({ key, link }) =>
+ isPageLinkDescriptor(link) ? (
+
+ ) : (
+
+ )
+ )}
>
);
}
/**
- * This component renders all of the `` and
+ * This component renders all the `` and
* `` tags for all the assets (data, modules, css) of
* a given page.
*
@@ -552,7 +524,7 @@ export function Meta() {
: routeModule.meta;
} else if (leafMeta) {
// We only assign the route's meta to the nearest leaf if there is no meta
- // export in the route. The meta function may return a falsey value which
+ // export in the route. The meta function may return a falsy value which
// is effectively the same as an empty array.
routeMeta = [...leafMeta];
}
@@ -749,7 +721,7 @@ export function Scripts(props: ScriptProps) {
// resolution by the subsequently streamed chunks.
// - __remixContext.r is a function that takes a routeID, key and value or error and resolves
// the promise created by __remixContext.n.
- // - __remixContext.t is a a map or routeId to keys to an object containing `e` and `r` methods
+ // - __remixContext.t is a map or routeId to keys to an object containing `e` and `r` methods
// to resolve or reject the promise created by __remixContext.n.
// - __remixContext.a is the active number of deferred scripts that should be rendered to match
// the SSR tree for hydration on the client.
diff --git a/packages/remix-react/package.json b/packages/remix-react/package.json
index fa9a7ab45c1..7a1f614665f 100644
--- a/packages/remix-react/package.json
+++ b/packages/remix-react/package.json
@@ -23,14 +23,14 @@
"devDependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.3.0",
- "@types/react": "^18.0.15",
+ "@types/react": "^18.2.20",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^5.1.6"
},
"peerDependencies": {
- "react": ">=16.8.0",
- "react-dom": ">=16.8.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0",
"typescript": "^5.1.0"
},
"peerDependenciesMeta": {
diff --git a/packages/remix-testing/create-remix-stub.tsx b/packages/remix-testing/create-remix-stub.tsx
index 06e4e346f9c..0c297cb500b 100644
--- a/packages/remix-testing/create-remix-stub.tsx
+++ b/packages/remix-testing/create-remix-stub.tsx
@@ -175,7 +175,6 @@ function createRouteModules(
modules[route.id!] = {
ErrorBoundary: undefined,
- // @ts-expect-error - types are still `agnostic` here
default: () => route.element,
handle: route.handle,
links: undefined,
diff --git a/packages/remix-testing/package.json b/packages/remix-testing/package.json
index 985e3f49d39..3c243984144 100644
--- a/packages/remix-testing/package.json
+++ b/packages/remix-testing/package.json
@@ -23,14 +23,14 @@
},
"devDependencies": {
"@types/node": "^18.17.1",
- "@types/react": "^18.0.24",
- "@types/react-dom": "^18.0.8",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^5.1.6"
},
"peerDependencies": {
- "react": "^17.0.0 || ^18.0.0",
+ "react": "^18.0.0",
"typescript": "^5.1.0"
},
"peerDependenciesMeta": {
diff --git a/scripts/playground/template/package.json b/scripts/playground/template/package.json
index e9b1a922547..9ed64c5ff06 100644
--- a/scripts/playground/template/package.json
+++ b/scripts/playground/template/package.json
@@ -37,8 +37,8 @@
"@remix-run/dev": "*",
"@types/bcryptjs": "^2.4.2",
"@types/node": "^18.17.1",
- "@types/react": "^18.0.17",
- "@types/react-dom": "^18.0.6",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"autoprefixer": "^10.4.8",
"cross-env": "^7.0.3",
"npm-run-all": "^4.1.5",
diff --git a/templates/arc/package.json b/templates/arc/package.json
index 524687fff60..1c202dea0f7 100644
--- a/templates/arc/package.json
+++ b/templates/arc/package.json
@@ -23,8 +23,8 @@
"@architect/architect": "^10.12.1",
"@remix-run/dev": "*",
"@remix-run/eslint-config": "*",
- "@types/react": "^18.0.35",
- "@types/react-dom": "^18.0.11",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"@types/source-map-support": "^0.5.6",
"eslint": "^8.38.0",
"typescript": "^5.1.6"
diff --git a/templates/cloudflare-pages/package.json b/templates/cloudflare-pages/package.json
index 4367e1c2e67..b6125b5864f 100644
--- a/templates/cloudflare-pages/package.json
+++ b/templates/cloudflare-pages/package.json
@@ -21,8 +21,8 @@
"@cloudflare/workers-types": "^4.20230518.0",
"@remix-run/dev": "*",
"@remix-run/eslint-config": "*",
- "@types/react": "^18.0.35",
- "@types/react-dom": "^18.0.11",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"eslint": "^8.38.0",
"typescript": "^5.1.0",
"wrangler": "^3.1.1"
diff --git a/templates/cloudflare-workers/package.json b/templates/cloudflare-workers/package.json
index 6392768dc3c..88d0b0c7c67 100644
--- a/templates/cloudflare-workers/package.json
+++ b/templates/cloudflare-workers/package.json
@@ -22,8 +22,8 @@
"@cloudflare/workers-types": "^4.20230518.0",
"@remix-run/dev": "*",
"@remix-run/eslint-config": "*",
- "@types/react": "^18.0.35",
- "@types/react-dom": "^18.0.11",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"eslint": "^8.38.0",
"typescript": "^5.1.6",
"wrangler": "^3.1.1"
diff --git a/templates/express/package.json b/templates/express/package.json
index 6b32b3ff58f..abb9935ba19 100644
--- a/templates/express/package.json
+++ b/templates/express/package.json
@@ -28,8 +28,8 @@
"@types/compression": "^1.7.2",
"@types/express": "^4.17.17",
"@types/morgan": "^1.9.4",
- "@types/react": "^18.0.35",
- "@types/react-dom": "^18.0.11",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"@types/source-map-support": "^0.5.6",
"chokidar": "^3.5.3",
"eslint": "^8.38.0",
diff --git a/templates/fly/package.json b/templates/fly/package.json
index 70b9c86faef..af4740f73ee 100644
--- a/templates/fly/package.json
+++ b/templates/fly/package.json
@@ -20,8 +20,8 @@
"devDependencies": {
"@remix-run/dev": "*",
"@remix-run/eslint-config": "*",
- "@types/react": "^18.0.35",
- "@types/react-dom": "^18.0.11",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"eslint": "^8.38.0",
"typescript": "^5.1.6"
},
diff --git a/templates/remix/package.json b/templates/remix/package.json
index 0f9a767fd22..eae4f571d9e 100644
--- a/templates/remix/package.json
+++ b/templates/remix/package.json
@@ -19,8 +19,8 @@
"devDependencies": {
"@remix-run/dev": "*",
"@remix-run/eslint-config": "*",
- "@types/react": "^18.0.35",
- "@types/react-dom": "^18.0.11",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
"eslint": "^8.38.0",
"typescript": "^5.1.6"
},
diff --git a/yarn.lock b/yarn.lock
index a53cdb0f658..089a1fb6d2a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2705,13 +2705,20 @@
resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz"
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
-"@types/react-dom@^18.0.0", "@types/react-dom@^18.0.6", "@types/react-dom@^18.0.8":
+"@types/react-dom@^18.0.0":
version "18.0.8"
resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.8.tgz"
integrity sha512-C3GYO0HLaOkk9dDAz3Dl4sbe4AKUGTCfFIZsz3n/82dPNN8Du533HzKatDxeUYWu24wJgMP1xICqkWk1YOLOIw==
dependencies:
"@types/react" "*"
+"@types/react-dom@^18.2.7":
+ version "18.2.7"
+ resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz#67222a08c0a6ae0a0da33c3532348277c70abb63"
+ integrity sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==
+ dependencies:
+ "@types/react" "*"
+
"@types/react-test-renderer@^18.0.0":
version "18.0.0"
resolved "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.0.0.tgz"
@@ -2719,7 +2726,7 @@
dependencies:
"@types/react" "*"
-"@types/react@*", "@types/react@^18.0.15", "@types/react@^18.0.24":
+"@types/react@*":
version "18.0.24"
resolved "https://registry.npmjs.org/@types/react/-/react-18.0.24.tgz"
integrity sha512-wRJWT6ouziGUy+9uX0aW4YOJxAY0bG6/AOk5AW5QSvZqI7dk6VBIbXvcVgIw/W5Jrl24f77df98GEKTJGOLx7Q==
@@ -2728,6 +2735,15 @@
"@types/scheduler" "*"
csstype "^3.0.2"
+"@types/react@^18.2.20":
+ version "18.2.20"
+ resolved "https://registry.npmjs.org/@types/react/-/react-18.2.20.tgz#1605557a83df5c8a2cc4eeb743b3dfc0eb6aaeb2"
+ integrity sha512-WKNtmsLWJM/3D5mG4U84cysVY31ivmyw85dE84fOCk5Hx78wezB/XEjVPWl2JTZ5FkEeaTJf+VgUAUn3PE7Isw==
+ dependencies:
+ "@types/prop-types" "*"
+ "@types/scheduler" "*"
+ csstype "^3.0.2"
+
"@types/resolve@1.17.1":
version "1.17.1"
resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz"