From 076b59fdd259be238d79bbbcda7fdb9c578adcd6 Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Fri, 13 Nov 2020 16:39:30 +0100 Subject: [PATCH] Revert "fix(gatsby): refresh browser when receiving update and runtime errored (#27467)" (#28034) This reverts commit f227e85728168d104ed0a7982823923dcd3bba62. --- .../content/error-recovery/page-query.json | 4 -- .../content/error-recovery/static-query.json | 4 -- .../error-handling/compile-error.js | 41 ----------- .../page-query-result-runtime-error.js | 69 ------------------- .../error-handling/query-validation-error.js | 45 ------------ .../error-handling/runtime-error.js | 48 ------------- .../static-query-result-runtime-error.js | 69 ------------------- .../cypress/support/commands.js | 27 +------- .../development-runtime/gatsby-config.js | 1 - e2e-tests/development-runtime/package.json | 1 - .../development-runtime/scripts/update.js | 18 +---- .../src/pages/error-handling/compile-error.js | 8 --- .../page-query-result-runtime-error.js | 25 ------- .../error-handling/query-validation-error.js | 19 ----- .../src/pages/error-handling/runtime-error.js | 8 --- .../static-query-result-runtime-error.js | 24 ------- .../gatsby/cache-dir/error-overlay-handler.js | 36 +--------- packages/gatsby/package.json | 2 +- yarn.lock | 5 -- 19 files changed, 5 insertions(+), 449 deletions(-) delete mode 100644 e2e-tests/development-runtime/content/error-recovery/page-query.json delete mode 100644 e2e-tests/development-runtime/content/error-recovery/static-query.json delete mode 100644 e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/compile-error.js delete mode 100644 e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/page-query-result-runtime-error.js delete mode 100644 e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/query-validation-error.js delete mode 100644 e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/runtime-error.js delete mode 100644 e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/static-query-result-runtime-error.js delete mode 100644 e2e-tests/development-runtime/src/pages/error-handling/compile-error.js delete mode 100644 e2e-tests/development-runtime/src/pages/error-handling/page-query-result-runtime-error.js delete mode 100644 e2e-tests/development-runtime/src/pages/error-handling/query-validation-error.js delete mode 100644 e2e-tests/development-runtime/src/pages/error-handling/runtime-error.js delete mode 100644 e2e-tests/development-runtime/src/pages/error-handling/static-query-result-runtime-error.js diff --git a/e2e-tests/development-runtime/content/error-recovery/page-query.json b/e2e-tests/development-runtime/content/error-recovery/page-query.json deleted file mode 100644 index 8d7de1d131960..0000000000000 --- a/e2e-tests/development-runtime/content/error-recovery/page-query.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "selector": "page-query", - "hasError": false -} diff --git a/e2e-tests/development-runtime/content/error-recovery/static-query.json b/e2e-tests/development-runtime/content/error-recovery/static-query.json deleted file mode 100644 index c7378bd85b5d5..0000000000000 --- a/e2e-tests/development-runtime/content/error-recovery/static-query.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "selector": "static-query", - "hasError": false -} diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/compile-error.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/compile-error.js deleted file mode 100644 index 6358db2a7df7e..0000000000000 --- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/compile-error.js +++ /dev/null @@ -1,41 +0,0 @@ -before(() => { - cy.exec( - `npm run update -- --file src/pages/error-handling/compile-error.js --restore` - ) -}) - -after(() => { - cy.exec( - `npm run update -- --file src/pages/error-handling/compile-error.js --restore` - ) -}) - -const errorPlaceholder = `// compile-error` -const errorReplacement = `a b` - -describe(`testing error overlay and ability to automatically recover from webpack compile errors`, () => { - it(`displays content initially (no errors yet)`, () => { - cy.visit(`/error-handling/compile-error/`).waitForRouteChange() - cy.getTestElement(`hot`).invoke(`text`).should(`contain`, `Working`) - }) - - it(`displays error with overlay on compilation errors`, () => { - cy.exec( - `npm run update -- --file src/pages/error-handling/compile-error.js --replacements "${errorPlaceholder}:${errorReplacement}" --exact` - ) - - cy.getOverlayIframe().contains(`Failed to compile`) - cy.getOverlayIframe().contains(`Parsing error: Unexpected token`) - cy.screenshot() - }) - - it(`can recover without need to refresh manually`, () => { - cy.exec( - `npm run update -- --file src/pages/error-handling/compile-error.js --replacements "Working:Updated" --replacements "${errorReplacement}:${errorPlaceholder}" --exact` - ) - - cy.getTestElement(`hot`).invoke(`text`).should(`contain`, `Updated`) - cy.assertNoOverlayIframe() - cy.screenshot() - }) -}) diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/page-query-result-runtime-error.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/page-query-result-runtime-error.js deleted file mode 100644 index 1faaae5204fd2..0000000000000 --- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/page-query-result-runtime-error.js +++ /dev/null @@ -1,69 +0,0 @@ -Cypress.on("uncaught:exception", (err, runnable) => { - // returning false here prevents Cypress from - // failing the test - return false -}) - -before(() => { - cy.exec( - `npm run update -- --file content/error-recovery/page-query.json --restore` - ) - cy.exec( - `npm run update -- --file src/pages/error-handling/page-query-result-runtime-error.js --restore` - ) -}) - -after(() => { - cy.exec( - `npm run update -- --file content/error-recovery/page-query.json --restore` - ) - cy.exec( - `npm run update -- --file src/pages/error-handling/page-query-result-runtime-error.js --restore` - ) -}) - -const errorPlaceholder = `false` -const errorReplacement = `true` - -describe(`testing error overlay and ability to automatically recover runtime errors cause by content changes (page queries variant)`, () => { - it(`displays content initially (no errors yet)`, () => { - cy.visit( - `/error-handling/page-query-result-runtime-error/` - ).waitForRouteChange() - cy.getTestElement(`hot`).invoke(`text`).should(`contain`, `Working`) - cy.getTestElement(`results`) - .invoke(`text`) - .should(`contain`, `"hasError": false`) - }) - - it(`displays error with overlay on runtime errors`, () => { - cy.exec( - `npm run update -- --file content/error-recovery/page-query.json --replacements "${errorPlaceholder}:${errorReplacement}" --exact` - ) - - // that's the exact error we throw and we expect to see that - cy.getOverlayIframe().contains(`Page query results caused runtime error`) - // contains details - cy.getOverlayIframe().contains( - `src/pages/error-handling/page-query-result-runtime-error.js` - ) - cy.screenshot() - }) - - it(`can recover without need to refresh manually`, () => { - cy.exec( - `npm run update -- --file content/error-recovery/page-query.json --replacements "${errorReplacement}:${errorPlaceholder}" --exact` - ) - cy.exec( - `npm run update -- --file src/pages/error-handling/page-query-result-runtime-error.js --replacements "Working:Updated" --exact` - ) - - cy.getTestElement(`hot`).invoke(`text`).should(`contain`, `Updated`) - cy.getTestElement(`results`) - .invoke(`text`) - .should(`contain`, `"hasError": false`) - - cy.assertNoOverlayIframe() - cy.screenshot() - }) -}) diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/query-validation-error.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/query-validation-error.js deleted file mode 100644 index 1fbbfb91c948b..0000000000000 --- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/query-validation-error.js +++ /dev/null @@ -1,45 +0,0 @@ -before(() => { - cy.exec( - `npm run update -- --file src/pages/error-handling/query-validation-error.js --restore` - ) -}) - -after(() => { - cy.exec( - `npm run update -- --file src/pages/error-handling/query-validation-error.js --restore` - ) -}) - -const errorPlaceholder = `# query-validation-error` -const errorReplacement = `fieldThatDoesNotExistOnSiteMapType` - -describe(`testing error overlay and ability to automatically recover from query extraction validation errors`, () => { - it(`displays content initially (no errors yet)`, () => { - cy.visit(`/error-handling/query-validation-error/`).waitForRouteChange() - cy.getTestElement(`hot`).invoke(`text`).should(`contain`, `Working`) - }) - - it(`displays error with overlay on compilation errors`, () => { - cy.exec( - `npm run update -- --file src/pages/error-handling/query-validation-error.js --replacements "${errorPlaceholder}:${errorReplacement}" --exact` - ) - - cy.getOverlayIframe().contains(`Failed to compile`) - cy.getOverlayIframe().contains(`There was an error in your GraphQL query`) - // make sure we mark location - cy.getOverlayIframe().contains( - `src/pages/error-handling/query-validation-error.js` - ) - cy.screenshot() - }) - - it(`can recover without need to refresh manually`, () => { - cy.exec( - `npm run update -- --file src/pages/error-handling/query-validation-error.js --replacements "Working:Updated" --replacements "${errorReplacement}:${errorPlaceholder}" --exact` - ) - - cy.getTestElement(`hot`).invoke(`text`).should(`contain`, `Updated`) - cy.assertNoOverlayIframe() - cy.screenshot() - }) -}) diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/runtime-error.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/runtime-error.js deleted file mode 100644 index d7a91d9e4c2c4..0000000000000 --- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/runtime-error.js +++ /dev/null @@ -1,48 +0,0 @@ -Cypress.on("uncaught:exception", (err, runnable) => { - // returning false here prevents Cypress from - // failing the test - return false -}) - -before(() => { - cy.exec( - `npm run update -- --file src/pages/error-handling/runtime-error.js --restore` - ) -}) - -after(() => { - cy.exec( - `npm run update -- --file src/pages/error-handling/runtime-error.js --restore` - ) -}) - -const errorPlaceholder = `// runtime-error` -const errorReplacement = `window.a.b.c.d.e.f.g()` - -describe(`testing error overlay and ability to automatically recover from runtime errors`, () => { - it(`displays content initially (no errors yet)`, () => { - cy.visit(`/error-handling/runtime-error/`).waitForRouteChange() - cy.getTestElement(`hot`).invoke(`text`).should(`contain`, `Working`) - }) - - it(`displays error with overlay on runtime errors`, () => { - cy.exec( - `npm run update -- --file src/pages/error-handling/runtime-error.js --replacements "${errorPlaceholder}:${errorReplacement}" --exact` - ) - - cy.getOverlayIframe().contains(`Cannot read property`) - // contains details - cy.getOverlayIframe().contains(`src/pages/error-handling/runtime-error.js`) - cy.screenshot() - }) - - it(`can recover without need to refresh manually`, () => { - cy.exec( - `npm run update -- --file src/pages/error-handling/runtime-error.js --replacements "Working:Updated" --replacements "${errorReplacement}:${errorPlaceholder}" --exact` - ) - - cy.getTestElement(`hot`).invoke(`text`).should(`contain`, `Updated`) - cy.assertNoOverlayIframe() - cy.screenshot() - }) -}) diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/static-query-result-runtime-error.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/static-query-result-runtime-error.js deleted file mode 100644 index da9f236e9ec61..0000000000000 --- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/error-handling/static-query-result-runtime-error.js +++ /dev/null @@ -1,69 +0,0 @@ -Cypress.on("uncaught:exception", (err, runnable) => { - // returning false here prevents Cypress from - // failing the test - return false -}) - -before(() => { - cy.exec( - `npm run update -- --file content/error-recovery/static-query.json --restore` - ) - cy.exec( - `npm run update -- --file src/pages/error-handling/static-query-result-runtime-error.js --restore` - ) -}) - -after(() => { - cy.exec( - `npm run update -- --file content/error-recovery/static-query.json --restore` - ) - cy.exec( - `npm run update -- --file src/pages/error-handling/static-query-result-runtime-error.js --restore` - ) -}) - -const errorPlaceholder = `false` -const errorReplacement = `true` - -describe(`testing error overlay and ability to automatically recover from runtime errors (static queries variant)`, () => { - it(`displays content initially (no errors yet)`, () => { - cy.visit( - `/error-handling/static-query-result-runtime-error/` - ).waitForRouteChange() - cy.getTestElement(`hot`).invoke(`text`).should(`contain`, `Working`) - cy.getTestElement(`results`) - .invoke(`text`) - .should(`contain`, `"hasError": false`) - }) - - it(`displays error with overlay on runtime errors`, () => { - cy.exec( - `npm run update -- --file content/error-recovery/static-query.json --replacements "${errorPlaceholder}:${errorReplacement}" --exact` - ) - - // that's the exact error we throw and we expect to see that - cy.getOverlayIframe().contains(`Static query results caused runtime error`) - // contains details - cy.getOverlayIframe().contains( - `src/pages/error-handling/static-query-result-runtime-error.js` - ) - cy.screenshot() - }) - - it(`can recover without need to refresh manually`, () => { - cy.exec( - `npm run update -- --file content/error-recovery/static-query.json --replacements "${errorReplacement}:${errorPlaceholder}" --exact` - ) - cy.exec( - `npm run update -- --file src/pages/error-handling/static-query-result-runtime-error.js --replacements "Working:Updated" --exact` - ) - - cy.getTestElement(`hot`).invoke(`text`).should(`contain`, `Updated`) - cy.getTestElement(`results`) - .invoke(`text`) - .should(`contain`, `"hasError": false`) - - cy.assertNoOverlayIframe() - cy.screenshot() - }) -}) diff --git a/e2e-tests/development-runtime/cypress/support/commands.js b/e2e-tests/development-runtime/cypress/support/commands.js index e17c55a140c7d..c30ad592e9874 100644 --- a/e2e-tests/development-runtime/cypress/support/commands.js +++ b/e2e-tests/development-runtime/cypress/support/commands.js @@ -24,7 +24,7 @@ Cypress.Commands.add(`lifecycleCallOrder`, expectedActionCallOrder => if (expectedActionCallOrderLength > actionsLength) { return false } - + let prevActionIndex = -1 for (let i = 0; i < actionsLength; i += 1) { const nextActionIndex = prevActionIndex + 1 @@ -81,29 +81,6 @@ Cypress.Commands.add( } ) -Cypress.Commands.add(`assertRoute`, route => { +Cypress.Commands.add(`assertRoute`, (route) => { cy.url().should(`equal`, `${window.location.origin}${route}`) }) - -// react-error-overlay is iframe, so this is just convenience helper -// https://www.cypress.io/blog/2020/02/12/working-with-iframes-in-cypress/#custom-command -Cypress.Commands.add(`getOverlayIframe`, () => { - // get the iframe > document > body - // and retry until the body element is not empty - return ( - cy - .get(`iframe`, { log: true, timeout: 150000 }) - .its(`0.contentDocument.body`) - .should(`not.be.empty`) - // wraps "body" DOM element to allow - // chaining more Cypress commands, like ".find(...)" - // https://on.cypress.io/wrap - .then(cy.wrap, { log: true }) - ) -}) - -Cypress.Commands.add(`assertNoOverlayIframe`, () => { - // get the iframe > document > body - // and retry until the body element is not empty - return cy.get(`iframe`, { log: true, timeout: 15000 }).should(`not.exist`) -}) diff --git a/e2e-tests/development-runtime/gatsby-config.js b/e2e-tests/development-runtime/gatsby-config.js index 46c122219fc6d..f5839118e7c9a 100644 --- a/e2e-tests/development-runtime/gatsby-config.js +++ b/e2e-tests/development-runtime/gatsby-config.js @@ -29,7 +29,6 @@ module.exports = { }, `gatsby-source-fake-data`, `gatsby-transformer-sharp`, - `gatsby-transformer-json`, { resolve: `gatsby-transformer-remark`, options: { diff --git a/e2e-tests/development-runtime/package.json b/e2e-tests/development-runtime/package.json index 06523242ed4f6..e06cfe8cdf2d4 100644 --- a/e2e-tests/development-runtime/package.json +++ b/e2e-tests/development-runtime/package.json @@ -13,7 +13,6 @@ "gatsby-plugin-sharp": "^2.0.37", "gatsby-seo": "^0.1.0", "gatsby-source-filesystem": "^2.0.33", - "gatsby-transformer-json": "^2.4.14", "gatsby-transformer-remark": "^2.3.12", "gatsby-transformer-sharp": "^2.1.19", "isomorphic-fetch": "^2.2.1", diff --git a/e2e-tests/development-runtime/scripts/update.js b/e2e-tests/development-runtime/scripts/update.js index 8d41f188a8635..87307b4516a00 100644 --- a/e2e-tests/development-runtime/scripts/update.js +++ b/e2e-tests/development-runtime/scripts/update.js @@ -34,29 +34,13 @@ const args = yargs ` ).trim(), type: `string`, - }) - .option(`restore`, { - default: false, - type: `boolean`, }).argv async function update() { const history = await getHistory() - const { file: fileArg, replacements, restore } = args + const { file: fileArg, replacements } = args const filePath = path.resolve(fileArg) - if (restore) { - const original = history.get(filePath) - if (original) { - await fs.writeFile(filePath, original, `utf-8`) - } else if (original === false) { - await fs.remove(filePath) - } else { - console.log(`Didn't make changes to "${fileArg}". Nothing to restore.`) - } - history.delete(filePath) - return - } let exists = true if (!fs.existsSync(filePath)) { exists = false diff --git a/e2e-tests/development-runtime/src/pages/error-handling/compile-error.js b/e2e-tests/development-runtime/src/pages/error-handling/compile-error.js deleted file mode 100644 index ff414984b6d2e..0000000000000 --- a/e2e-tests/development-runtime/src/pages/error-handling/compile-error.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from "react" - -function CompileError() { - // compile-error - return

Working

-} - -export default CompileError diff --git a/e2e-tests/development-runtime/src/pages/error-handling/page-query-result-runtime-error.js b/e2e-tests/development-runtime/src/pages/error-handling/page-query-result-runtime-error.js deleted file mode 100644 index 151e250ae84cf..0000000000000 --- a/e2e-tests/development-runtime/src/pages/error-handling/page-query-result-runtime-error.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from "react" -import { graphql } from "gatsby" - -function PageQueryRuntimeError({ data }) { - console.log(data.errorRecoveryJson) - if (data.errorRecoveryJson.hasError) { - throw new Error(`Page query results caused runtime error`) - } - return ( - <> -

Working

-
{JSON.stringify(data, null, 2)}
- - ) -} - -export default PageQueryRuntimeError - -export const query = graphql` - { - errorRecoveryJson(selector: { eq: "page-query" }) { - hasError - } - } -` diff --git a/e2e-tests/development-runtime/src/pages/error-handling/query-validation-error.js b/e2e-tests/development-runtime/src/pages/error-handling/query-validation-error.js deleted file mode 100644 index 5f430dde4c865..0000000000000 --- a/e2e-tests/development-runtime/src/pages/error-handling/query-validation-error.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from "react" -import { graphql } from "gatsby" - -function QueryValidationError() { - return

Working

-} - -export default QueryValidationError - -export const query = graphql` - { - site { - siteMetadata { - title - # query-validation-error - } - } - } -` diff --git a/e2e-tests/development-runtime/src/pages/error-handling/runtime-error.js b/e2e-tests/development-runtime/src/pages/error-handling/runtime-error.js deleted file mode 100644 index 05b81b19d2c98..0000000000000 --- a/e2e-tests/development-runtime/src/pages/error-handling/runtime-error.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from "react" - -function RuntimeError() { - // runtime-error - return

Working

-} - -export default RuntimeError diff --git a/e2e-tests/development-runtime/src/pages/error-handling/static-query-result-runtime-error.js b/e2e-tests/development-runtime/src/pages/error-handling/static-query-result-runtime-error.js deleted file mode 100644 index 98456cc464327..0000000000000 --- a/e2e-tests/development-runtime/src/pages/error-handling/static-query-result-runtime-error.js +++ /dev/null @@ -1,24 +0,0 @@ -import React from "react" -import { graphql, useStaticQuery } from "gatsby" - -function StaticQueryRuntimeError() { - const data = useStaticQuery(graphql` - { - errorRecoveryJson(selector: { eq: "static-query" }) { - hasError - } - } - `) - console.log(data.errorRecoveryJson) - if (data.errorRecoveryJson.hasError) { - throw new Error(`Static query results caused runtime error`) - } - return ( - <> -

Working

-
{JSON.stringify(data, null, 2)}
- - ) -} - -export default StaticQueryRuntimeError diff --git a/packages/gatsby/cache-dir/error-overlay-handler.js b/packages/gatsby/cache-dir/error-overlay-handler.js index 62ac7e3d18882..f02b70a2c0cc1 100644 --- a/packages/gatsby/cache-dir/error-overlay-handler.js +++ b/packages/gatsby/cache-dir/error-overlay-handler.js @@ -14,44 +14,10 @@ const ErrorOverlay = { if (process.env.GATSBY_HOT_LOADER !== `fast-refresh`) { // Report runtime errors - let registeredReloadListeners = false - function onError() { - if (registeredReloadListeners) { - return - } - - // Inspired by `react-dev-utils` HMR client: - // If there was unhandled error, reload browser - // on next HMR update - module.hot.addStatusHandler(status => { - if (status === `apply` || status === `idle`) { - window.location.reload() - } - }) - - // Additionally in Gatsby case query result updates can cause - // runtime error and also fix them, so reload on data updates - // as well - ___emitter.on(`pageQueryResult`, () => { - window.location.reload() - }) - ___emitter.on(`staticQueryResult`, () => { - window.location.reload() - }) - - registeredReloadListeners = true - } ReactErrorOverlay.startReportingRuntimeErrors({ - onError, + onError: () => {}, filename: `/commons.js`, }) - - // ReactErrorOverlay `onError` handler is triggered pretty late - // so we attach same error/unhandledrejection as ReactErrorOverlay - // to be able to detect runtime error and setup listeners faster - window.addEventListener(`error`, onError) - window.addEventListener(`unhandledrejection`, onError) - ReactErrorOverlay.setEditorHandler(errorLocation => window.fetch( `/__open-stack-frame-in-editor?fileName=` + diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index dfb1724b59875..a22156db54e4a 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -125,7 +125,7 @@ "query-string": "^6.13.1", "raw-loader": "^0.5.1", "react-dev-utils": "^4.2.3", - "react-error-overlay": "^6.0.7", + "react-error-overlay": "^3.0.0", "react-hot-loader": "^4.12.21", "react-refresh": "^0.8.3", "redux": "^4.0.5", diff --git a/yarn.lock b/yarn.lock index 53133d8fef6a8..ff1af4456dc3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19900,11 +19900,6 @@ react-error-overlay@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-3.0.0.tgz#c2bc8f4d91f1375b3dad6d75265d51cd5eeaf655" -react-error-overlay@^6.0.7: - version "6.0.7" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108" - integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA== - react-fast-compare@^2.0.1: version "2.0.4" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"