diff --git a/.changeset/lovely-seals-sin.md b/.changeset/lovely-seals-sin.md new file mode 100644 index 00000000000..b4372229c43 --- /dev/null +++ b/.changeset/lovely-seals-sin.md @@ -0,0 +1,5 @@ +--- +"@remix-run/react": patch +--- + +Ensure useFetcher is stable across re-renders in backwards-compatibility layer diff --git a/packages/remix-react/CHANGELOG.md b/packages/remix-react/CHANGELOG.md index 0a20179c05a..4de96c5bc6c 100644 --- a/packages/remix-react/CHANGELOG.md +++ b/packages/remix-react/CHANGELOG.md @@ -14,6 +14,7 @@ - Add `future.v2_errorBoundary` flag to opt-into v2 `ErrorBoundary` behavior. This removes the separate `CatchBoundary` and `ErrorBoundary` and consolidates them into a single `ErrorBoundary` following the logic used by `errorElement` in React Router. You can then use `isRouteErrorResponse` to differentiate between thrown `Response`/`Error` instances. ([#4918](https://github.com/remix-run/remix/pull/4918)) ```jsx + /* eslint-disable import/no-extraneous-dependencies */ // Current (Remix v1 default) import { useCatch } from "@remix-run/react"; @@ -29,7 +30,10 @@ export function ErrorBoundary({ error }) { return

{error.message}

; } + ``` + ```jsx + /* eslint-disable import/no-extraneous-dependencies */ // Using future.v2_errorBoundary import { isRouteErrorResponse, useRouteError } from "@remix-run/react"; diff --git a/packages/remix-react/components.tsx b/packages/remix-react/components.tsx index d3617cbee42..4066ee2ea71 100644 --- a/packages/remix-react/components.tsx +++ b/packages/remix-react/components.tsx @@ -1359,21 +1359,24 @@ export function useFetcher(): FetcherWithComponents< SerializeFrom > { let fetcherRR = useFetcherRR(); - let remixFetcher = convertRouterFetcherToRemixFetcher({ - state: fetcherRR.state, - data: fetcherRR.data, - formMethod: fetcherRR.formMethod, - formAction: fetcherRR.formAction, - formData: fetcherRR.formData, - formEncType: fetcherRR.formEncType, - " _hasFetcherDoneAnything ": fetcherRR[" _hasFetcherDoneAnything "], - }); - return { - ...remixFetcher, - load: fetcherRR.load, - submit: fetcherRR.submit, - Form: fetcherRR.Form, - }; + + return React.useMemo(() => { + let remixFetcher = convertRouterFetcherToRemixFetcher({ + state: fetcherRR.state, + data: fetcherRR.data, + formMethod: fetcherRR.formMethod, + formAction: fetcherRR.formAction, + formData: fetcherRR.formData, + formEncType: fetcherRR.formEncType, + " _hasFetcherDoneAnything ": fetcherRR[" _hasFetcherDoneAnything "], + }); + return { + ...remixFetcher, + load: fetcherRR.load, + submit: fetcherRR.submit, + Form: fetcherRR.Form, + }; + }, [fetcherRR]); } function convertRouterFetcherToRemixFetcher( diff --git a/packages/remix-server-runtime/CHANGELOG.md b/packages/remix-server-runtime/CHANGELOG.md index 2c22bd91edf..68f0a74b779 100644 --- a/packages/remix-server-runtime/CHANGELOG.md +++ b/packages/remix-server-runtime/CHANGELOG.md @@ -13,6 +13,7 @@ - Add `future.v2_errorBoundary` flag to opt-into v2 `ErrorBoundary` behavior. This removes the separate `CatchBoundary` and `ErrorBoundary` and consolidates them into a single `ErrorBoundary` following the logic used by `errorElement` in React Router. You can then use `isRouteErrorResponse` to differentiate between thrown `Response`/`Error` instances. ([#4918](https://github.com/remix-run/remix/pull/4918)) ```jsx + /* eslint-disable import/no-extraneous-dependencies */ // Current (Remix v1 default) import { useCatch } from "@remix-run/react"; @@ -28,7 +29,10 @@ export function ErrorBoundary({ error }) { return

{error.message}

; } + ``` + ```jsx + /* eslint-disable import/no-extraneous-dependencies */ // Using future.v2_errorBoundary import { isRouteErrorResponse, useRouteError } from "@remix-run/react"; diff --git a/yarn.lock b/yarn.lock index 9f9b624f585..e03edb52d8d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2248,72 +2248,11 @@ "@changesets/types" "^5.0.0" dotenv "^8.1.0" -"@remix-run/dev@1.10.0": - version "1.10.0" - resolved "https://registry.npmjs.org/@remix-run/dev/-/dev-1.10.0.tgz#3a5b2cb52eee6da1d993538a44a307375bf694df" - integrity sha512-WBbxkPSkN1LQx0gdzGT+VBSbQLGiFW/Q7HaAYBxV7Wd7DdByk61GPz9CRb1K9a7eWGJ+FzZeYvRwqYkz7moRgA== - dependencies: - "@babel/core" "^7.18.6" - "@babel/plugin-syntax-jsx" "^7.18.6" - "@babel/plugin-syntax-typescript" "^7.20.0" - "@babel/preset-env" "^7.18.6" - "@babel/preset-typescript" "^7.18.6" - "@babel/types" "^7.20.2" - "@esbuild-plugins/node-modules-polyfill" "^0.1.4" - "@npmcli/package-json" "^2.0.0" - "@remix-run/server-runtime" "1.10.0" - arg "^5.0.1" - cacache "^15.0.5" - chalk "^4.1.2" - chokidar "^3.5.1" - dotenv "^16.0.0" - esbuild "0.16.3" - execa "5.1.1" - exit-hook "2.2.1" - express "^4.17.1" - fast-glob "3.2.11" - fs-extra "^10.0.0" - get-port "^5.1.1" - gunzip-maybe "^1.4.2" - inquirer "^8.2.1" - jscodeshift "^0.13.1" - jsesc "3.0.2" - json5 "^2.2.1" - lodash "^4.17.21" - lodash.debounce "^4.0.8" - minimatch "^3.0.4" - node-fetch "^2.6.7" - ora "^5.4.1" - prettier "2.7.1" - pretty-ms "^7.0.1" - proxy-agent "^5.0.0" - recast "^0.21.5" - remark-frontmatter "4.0.1" - remark-mdx-frontmatter "^1.0.1" - semver "^7.3.7" - sort-package-json "^1.55.0" - tar-fs "^2.1.1" - tsconfig-paths "^4.0.0" - ws "^7.4.5" - xdm "^2.0.0" - "@remix-run/router@1.3.0-pre.2": version "1.3.0-pre.2" resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.3.0-pre.2.tgz#13f8ac419d272558a9d48f6efe40a8909f6ff212" integrity sha512-XWpQkUMfuJy5BPA+fivgJtKPiRu1VC5M3LdrUw6Wb310liR3LUIUmY2b5xP6kpcbpIQOTMgF4NVrdwZ4NRG0lA== -"@remix-run/server-runtime@1.10.0": - version "1.10.0" - resolved "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-1.10.0.tgz#d498332a8b6f7ee9a2dca5ac987619a1bce8f9e1" - integrity sha512-2Hlyv96JI4R3ygsF+zgC7NxfeRO1lqNxH/0GpPniyZIfq3JT4+PmTOgbx7HSsj/jgJzDfCyhwjymGYK84mBMKg== - dependencies: - "@remix-run/router" "1.3.0-pre.2" - "@types/cookie" "^0.4.0" - "@web3-storage/multipart-parser" "^1.0.0" - cookie "^0.4.1" - set-cookie-parser "^2.4.8" - source-map "^0.7.3" - "@remix-run/web-blob@^3.0.3", "@remix-run/web-blob@^3.0.4": version "3.0.4" resolved "https://registry.npmjs.org/@remix-run/web-blob/-/web-blob-3.0.4.tgz"