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(<RemixBrowser />, document); +hydrateRoot(document, <RemixBrowser />); 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( - <RemixServer context={remixContext} url={request.url} /> - ); + return new Promise((resolve, reject) => { + let didError = false; + + let { pipe, abort } = renderToPipeableStream( + <RemixServer context={remixContext} url={request.url} />, + { + onShellReady() { + let body = new PassThrough(); - responseHeaders.set("Content-Type", "text/html"); + responseHeaders.set("Content-Type", "text/html"); - return new Response("<!DOCTYPE html>" + 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<ClientRoute>[]; - routeData: { [routeId: string]: RouteData }; + routeData: RouteData; actionData?: RouteData; pendingLocation?: Location; appState: AppState; @@ -719,7 +719,7 @@ export function Meta() { } if (name === "title") { - return <title key="title">{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"