diff --git a/.changeset/nasty-cars-care.md b/.changeset/nasty-cars-care.md
new file mode 100644
index 00000000000..d89994d6c84
--- /dev/null
+++ b/.changeset/nasty-cars-care.md
@@ -0,0 +1,5 @@
+---
+"@remix-run/react": patch
+---
+
+React 18 gets more strict with types, this adds a runtime cast to a string for the `
` tag value.
diff --git a/examples/blog-tutorial/package.json b/examples/blog-tutorial/package.json
index c970016f2c5..bc1787f31df 100644
--- a/examples/blog-tutorial/package.json
+++ b/examples/blog-tutorial/package.json
@@ -46,7 +46,7 @@
"@testing-library/cypress": "^8.0.2",
"@testing-library/dom": "^8.13.0",
"@testing-library/jest-dom": "^5.16.4",
- "@testing-library/react": "^12.1.5",
+ "@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"@types/eslint": "^8.4.1",
"@types/marked": "^4.0.3",
diff --git a/integration/helpers/node-template/app/entry.client.tsx b/integration/helpers/node-template/app/entry.client.tsx
index 3eec1fd0a02..d7ef6febb0d 100644
--- a/integration/helpers/node-template/app/entry.client.tsx
+++ b/integration/helpers/node-template/app/entry.client.tsx
@@ -1,4 +1,4 @@
+import { hydrateRoot } from "react-dom/client";
import { RemixBrowser } from "@remix-run/react";
-import { hydrate } from "react-dom";
-hydrate(, document);
+hydrateRoot(document, );
diff --git a/integration/helpers/node-template/app/entry.server.tsx b/integration/helpers/node-template/app/entry.server.tsx
index aa0aa0978b1..2a3e6678939 100644
--- a/integration/helpers/node-template/app/entry.server.tsx
+++ b/integration/helpers/node-template/app/entry.server.tsx
@@ -1,6 +1,10 @@
+import { PassThrough } from "stream";
+import { renderToPipeableStream } from "react-dom/server";
import type { EntryContext } from "@remix-run/node";
+import { Response } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
-import { renderToString } from "react-dom/server";
+
+const ABORT_DELAY = 5000;
export default function handleRequest(
request: Request,
@@ -8,14 +12,34 @@ export default function handleRequest(
responseHeaders: Headers,
remixContext: EntryContext
) {
- let markup = renderToString(
-
- );
+ return new Promise((resolve, reject) => {
+ let didError = false;
+
+ let { pipe, abort } = renderToPipeableStream(
+ ,
+ {
+ onShellReady() {
+ let body = new PassThrough();
- responseHeaders.set("Content-Type", "text/html");
+ responseHeaders.set("Content-Type", "text/html");
- return new Response("" + markup, {
- status: responseStatusCode,
- headers: responseHeaders,
+ resolve(
+ new Response(body, {
+ status: didError ? 500 : responseStatusCode,
+ headers: responseHeaders,
+ })
+ );
+ pipe(body);
+ },
+ onShellError(err) {
+ reject(err);
+ },
+ onError(error) {
+ didError = true;
+ console.error(error);
+ },
+ }
+ );
+ setTimeout(abort, ABORT_DELAY);
});
}
diff --git a/package.json b/package.json
index e81d1292384..876b692f39a 100644
--- a/package.json
+++ b/package.json
@@ -67,7 +67,7 @@
"@rollup/plugin-node-resolve": "^11.0.1",
"@testing-library/cypress": "^8.0.2",
"@testing-library/jest-dom": "^5.16.2",
- "@testing-library/react": "^12.1.3",
+ "@testing-library/react": "^13.3.0",
"@types/cheerio": "^0.22.22",
"@types/cross-spawn": "^6.0.2",
"@types/glob": "7.2.0",
@@ -75,9 +75,9 @@
"@types/jsonfile": "^6.1.0",
"@types/lodash": "^4.14.182",
"@types/node-fetch": "^2.5.7",
- "@types/react": "^17.0.24",
- "@types/react-dom": "^17.0.9",
- "@types/react-test-renderer": "^17.0.1",
+ "@types/react": "^18.0.15",
+ "@types/react-dom": "^18.0.6",
+ "@types/react-test-renderer": "^18.0.0",
"@types/retry": "^0.12.0",
"@types/semver": "^7.3.4",
"@types/ssri": "^7.1.0",
@@ -104,8 +104,8 @@
"npm-run-all": "^4.1.5",
"prettier": "2.7.1",
"prompt-confirm": "^2.0.4",
- "react": "^17.0.2",
- "react-dom": "^17.0.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"remark": "14.0.2",
"remark-frontmatter": "4.0.1",
"remark-gfm": "3.0.1",
diff --git a/packages/remix-dev/__tests__/fixtures/replace-remix-imports/package.json b/packages/remix-dev/__tests__/fixtures/replace-remix-imports/package.json
index 2a9a22a6540..869f5236d6a 100644
--- a/packages/remix-dev/__tests__/fixtures/replace-remix-imports/package.json
+++ b/packages/remix-dev/__tests__/fixtures/replace-remix-imports/package.json
@@ -24,8 +24,8 @@
"@remix-run/react": "1.3.4",
"@remix-run/serve": "1.3.4",
"marked": "^4.0.12",
- "react": "^17.0.2",
- "react-dom": "^17.0.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"remix": "1.3.4",
"tiny-invariant": "^1.2.0"
},
@@ -35,12 +35,12 @@
"@remix-run/eslint-config": "1.3.4",
"@testing-library/cypress": "^8.0.2",
"@testing-library/jest-dom": "^5.16.2",
- "@testing-library/react": "^12.1.4",
+ "@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"@types/eslint": "^8.4.1",
"@types/marked": "^4.0.2",
- "@types/react": "^17.0.40",
- "@types/react-dom": "^17.0.13",
+ "@types/react": "^18.0.15",
+ "@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^1.2.0",
"c8": "^7.11.0",
"cross-env": "^7.0.3",
diff --git a/packages/remix-dev/__tests__/migrations/fixtures/indie-stack/package.json b/packages/remix-dev/__tests__/migrations/fixtures/indie-stack/package.json
index fb44f0fbffc..a077f189319 100644
--- a/packages/remix-dev/__tests__/migrations/fixtures/indie-stack/package.json
+++ b/packages/remix-dev/__tests__/migrations/fixtures/indie-stack/package.json
@@ -8,14 +8,14 @@
"@remix-run/node": "*",
"@remix-run/react": "*",
"@remix-run/serve": "*",
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
},
"devDependencies": {
"@remix-run/dev": "*",
"@types/node": "^17.0.35",
- "@types/react": "^17.0.45",
- "@types/react-dom": "^17.0.17",
+ "@types/react": "^18.0.15",
+ "@types/react-dom": "^18.0.6",
"typescript": "^4.7.4"
},
"engines": {
diff --git a/packages/remix-eslint-config/package.json b/packages/remix-eslint-config/package.json
index 69330cca95a..f05ce1f888f 100644
--- a/packages/remix-eslint-config/package.json
+++ b/packages/remix-eslint-config/package.json
@@ -43,8 +43,8 @@
"devDependencies": {
"@types/eslint": "^8.4.1",
"eslint": "^8.1.0",
- "react": "^17.0.2",
- "react-dom": "^17.0.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"typescript": "^4.7.4"
},
"peerDependencies": {
diff --git a/packages/remix-express/tsconfig.json b/packages/remix-express/tsconfig.json
index 64e50c9eaf1..85d9324886d 100644
--- a/packages/remix-express/tsconfig.json
+++ b/packages/remix-express/tsconfig.json
@@ -4,6 +4,7 @@
"compilerOptions": {
"lib": ["ES2019", "DOM.Iterable"],
"target": "ES2019",
+ "skipLibCheck": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
diff --git a/packages/remix-react/__tests__/setup.ts b/packages/remix-react/__tests__/setup.ts
index fba7a393e92..451031301ac 100644
--- a/packages/remix-react/__tests__/setup.ts
+++ b/packages/remix-react/__tests__/setup.ts
@@ -1,9 +1,3 @@
-// @ts-nocheck
-import * as AbortController from "abort-controller";
-import * as nodeFetch from "@remix-run/node/fetch";
+import { installGlobals } from "@remix-run/node";
-global.AbortController = AbortController.AbortController;
-global.Headers = nodeFetch.Headers;
-global.Response = nodeFetch.Response;
-global.Request = nodeFetch.Request;
-global.fetch = nodeFetch;
+installGlobals();
diff --git a/packages/remix-react/components.tsx b/packages/remix-react/components.tsx
index b7ec24415f3..3a6bef315da 100644
--- a/packages/remix-react/components.tsx
+++ b/packages/remix-react/components.tsx
@@ -57,7 +57,7 @@ import type { Transition, Fetcher, Submission } from "./transition";
interface RemixEntryContextType {
manifest: AssetsManifest;
matches: BaseRouteMatch[];
- routeData: { [routeId: string]: RouteData };
+ routeData: RouteData;
actionData?: RouteData;
pendingLocation?: Location;
appState: AppState;
@@ -719,7 +719,7 @@ export function Meta() {
}
if (name === "title") {
- return {value};
+ return {String(value)};
}
// Open Graph tags use the `property` attribute, while other meta tags
diff --git a/packages/remix-react/package.json b/packages/remix-react/package.json
index 982d08314e7..7a7c23d85bf 100644
--- a/packages/remix-react/package.json
+++ b/packages/remix-react/package.json
@@ -22,10 +22,10 @@
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.2",
- "@testing-library/react": "^12.1.3",
+ "@testing-library/react": "^13.3.0",
"abort-controller": "^3.0.0",
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
},
"peerDependencies": {
"react": ">=16.8",
diff --git a/packages/remix-server-runtime/package.json b/packages/remix-server-runtime/package.json
index 840b9e0c44f..98814f245f4 100644
--- a/packages/remix-server-runtime/package.json
+++ b/packages/remix-server-runtime/package.json
@@ -28,8 +28,8 @@
"@remix-run/web-file": "^3.0.2",
"@types/jsesc": "^2.5.1",
"@types/set-cookie-parser": "^2.4.1",
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
},
"peerDependencies": {
"react": ">=16.8",
diff --git a/scripts/playground/template/package.json b/scripts/playground/template/package.json
index 53cb034584f..7adf6275bc2 100644
--- a/scripts/playground/template/package.json
+++ b/scripts/playground/template/package.json
@@ -30,8 +30,8 @@
"express": "^4.18.1",
"get-port": "^6.1.2",
"morgan": "^1.10.0",
- "react": "^18.1.0",
- "react-dom": "^18.1.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"tiny-invariant": "^1.2.0"
},
"devDependencies": {
@@ -39,8 +39,8 @@
"@remix-run/dev": "^1.4.3",
"@types/bcryptjs": "^2.4.2",
"@types/node": "^17.0.31",
- "@types/react": "^17.0.44",
- "@types/react-dom": "^17.0.16",
+ "@types/react": "^18.0.15",
+ "@types/react-dom": "^18.0.6",
"autoprefixer": "^10.4.7",
"cross-env": "^7.0.3",
"npm-run-all": "^4.1.5",
diff --git a/yarn.lock b/yarn.lock
index af120d1b234..ceff2771f75 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2460,7 +2460,7 @@
"@babel/runtime" "^7.14.6"
"@testing-library/dom" "^8.1.0"
-"@testing-library/dom@^8.0.0", "@testing-library/dom@^8.1.0", "@testing-library/dom@^8.11.1":
+"@testing-library/dom@^8.1.0", "@testing-library/dom@^8.11.1":
version "8.11.3"
resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-8.11.3.tgz"
integrity sha512-9LId28I+lx70wUiZjLvi1DB/WT2zGOxUh46glrSNMaWVx849kKAluezVzZrXJfTKKoQTmEOutLes/bHg4Bj3aA==
@@ -2474,6 +2474,20 @@
lz-string "^1.4.4"
pretty-format "^27.0.2"
+"@testing-library/dom@^8.5.0":
+ version "8.16.0"
+ resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-8.16.0.tgz#d6fc50250aed17b1035ca1bd64655e342db3936a"
+ integrity sha512-uxF4zmnLHHDlmW4l+0WDjcgLVwCvH+OVLpD8Dfp+Bjfz85prwxWGbwXgJdLtkgjD0qfOzkJF9SmA6YZPsMYX4w==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/runtime" "^7.12.5"
+ "@types/aria-query" "^4.2.0"
+ aria-query "^5.0.0"
+ chalk "^4.1.0"
+ dom-accessibility-api "^0.5.9"
+ lz-string "^1.4.4"
+ pretty-format "^27.0.2"
+
"@testing-library/jest-dom@^5.16.2":
version "5.16.2"
resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz"
@@ -2489,14 +2503,14 @@
lodash "^4.17.15"
redent "^3.0.0"
-"@testing-library/react@^12.1.3":
- version "12.1.3"
- resolved "https://registry.npmjs.org/@testing-library/react/-/react-12.1.3.tgz"
- integrity sha512-oCULRXWRrBtC9m6G/WohPo1GLcLesH7T4fuKzRAKn1CWVu9BzXtqLXDDTA6KhFNNtRwLtfSMr20HFl+Qrdrvmg==
+"@testing-library/react@^13.3.0":
+ version "13.3.0"
+ resolved "https://registry.npmjs.org/@testing-library/react/-/react-13.3.0.tgz#bf298bfbc5589326bbcc8052b211f3bb097a97c5"
+ integrity sha512-DB79aA426+deFgGSjnf5grczDPiL4taK3hFaa+M5q7q20Kcve9eQottOG5kZ74KEr55v0tU2CQormSSDK87zYQ==
dependencies:
"@babel/runtime" "^7.12.5"
- "@testing-library/dom" "^8.0.0"
- "@types/react-dom" "*"
+ "@testing-library/dom" "^8.5.0"
+ "@types/react-dom" "^18.0.0"
"@tootallnate/once@1":
version "1.1.2"
@@ -2947,21 +2961,21 @@
resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz"
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
-"@types/react-dom@*", "@types/react-dom@^17.0.9":
- version "17.0.11"
- resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz"
- integrity sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==
+"@types/react-dom@^18.0.0", "@types/react-dom@^18.0.6":
+ version "18.0.6"
+ resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz#36652900024842b74607a17786b6662dd1e103a1"
+ integrity sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==
dependencies:
"@types/react" "*"
-"@types/react-test-renderer@^17.0.1":
- version "17.0.1"
- resolved "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz"
- integrity sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==
+"@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#7b7f69ca98821ea5501b21ba24ea7b6139da2243"
+ integrity sha512-C7/5FBJ3g3sqUahguGi03O79b8afNeSD6T8/GU50oQrJCU0bVCCGQHaGKUbg2Ce8VQEEqTw8/HiS6lXHHdgkdQ==
dependencies:
"@types/react" "*"
-"@types/react@*", "@types/react@^17.0.24":
+"@types/react@*":
version "17.0.24"
resolved "https://registry.npmjs.org/@types/react/-/react-17.0.24.tgz"
integrity sha512-eIpyco99gTH+FTI3J7Oi/OH8MZoFMJuztNRimDOJwH4iGIsKV2qkGnk4M9VzlaVWeEEWLWSQRy0FEA0Kz218cg==
@@ -2970,6 +2984,15 @@
"@types/scheduler" "*"
csstype "^3.0.2"
+"@types/react@^18.0.15":
+ version "18.0.15"
+ resolved "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz#d355644c26832dc27f3e6cbf0c4f4603fc4ab7fe"
+ integrity sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==
+ 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"
@@ -10477,14 +10500,13 @@ raw-body@2.4.3:
iconv-lite "0.4.24"
unpipe "1.0.0"
-react-dom@^17.0.2:
- version "17.0.2"
- resolved "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz"
- integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
+react-dom@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
+ integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
dependencies:
loose-envify "^1.1.0"
- object-assign "^4.1.1"
- scheduler "^0.20.2"
+ scheduler "^0.23.0"
react-is@^16.8.1:
version "16.13.1"
@@ -10511,13 +10533,12 @@ react-router@6.2.2:
dependencies:
history "^5.2.0"
-react@^17.0.2:
- version "17.0.2"
- resolved "https://registry.npmjs.org/react/-/react-17.0.2.tgz"
- integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
+react@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
+ integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
dependencies:
loose-envify "^1.1.0"
- object-assign "^4.1.1"
read-pkg-up@^7.0.1:
version "7.0.1"
@@ -11047,13 +11068,12 @@ saxes@^5.0.1:
dependencies:
xmlchars "^2.2.0"
-scheduler@^0.20.2:
- version "0.20.2"
- resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz"
- integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
+scheduler@^0.23.0:
+ version "0.23.0"
+ resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
+ integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
dependencies:
loose-envify "^1.1.0"
- object-assign "^4.1.1"
"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0:
version "5.7.1"