diff --git a/karma.conf.js b/karma.conf.js index 3523c19..e857cd0 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,6 +1,6 @@ process.env.CHROME_BIN = require('puppeteer').executablePath() -module.exports = function(config) { +module.exports = function (config) { config.set({ frameworks: ['mocha'], @@ -20,6 +20,10 @@ module.exports = function(config) { webpack: { mode: 'development', devtool: 'inline-source-map', + node: { + fs: 'empty', + module: 'empty', + }, module: { rules: [ { diff --git a/package.json b/package.json index ca355c8..cfa5dff 100644 --- a/package.json +++ b/package.json @@ -60,8 +60,8 @@ "@babel/preset-typescript": "^7.10.1", "@babel/register": "^7.10.1", "@testing-library/react": "^10.2.1", + "@testing-library/react-hooks": "^3.4.2", "@types/debounce": "^1.2.0", - "@types/expect": "^24.3.0", "@types/lodash-es": "^4.17.3", "@types/mocha": "^7.0.2", "@types/react": "^16.9.35", @@ -91,6 +91,7 @@ "puppeteer": "^3.3.0", "react": "^16.11.0", "react-dom": "^16.11.0", + "react-test-renderer": "^17.0.1", "resize-observer-polyfill": "^1.5.1", "rimraf": "^3.0.2", "rollup": "^2.13.1", diff --git a/src/web/index.spec.tsx b/src/web/index.spec.tsx index d8ff80e..a094e8a 100644 --- a/src/web/index.spec.tsx +++ b/src/web/index.spec.tsx @@ -2,6 +2,7 @@ import * as React from 'react' import styled, { createGlobalStyle } from 'styled-components' import expect from 'expect' import { render, cleanup, RenderResult, fireEvent } from '@testing-library/react' +import { renderHook } from '@testing-library/react-hooks' import Polyfill from 'resize-observer-polyfill' import useMeasure, { Options } from '.' @@ -27,8 +28,8 @@ const Wrapper = styled.div` ` const Box = styled.div<{ big: boolean }>` - width: ${p => (p.big ? 400 : 200)}px; - height: ${p => (p.big ? 400 : 200)}px; + width: ${(p) => (p.big ? 400 : 200)}px; + height: ${(p) => (p.big ? 400 : 200)}px; overflow: hidden; font-size: 8px; ` @@ -38,8 +39,8 @@ const Box = styled.div<{ big: boolean }>` */ const getBounds = (tools: RenderResult): ClientRect => JSON.parse(tools.getByTestId('box').innerHTML) -const nextFrame = () => new Promise(resolve => setTimeout(resolve, 1000 / 60)) -const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) +const nextFrame = () => new Promise((resolve) => setTimeout(resolve, 1000 / 60)) +const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) function ignoreWindowErrors(test: () => void) { const onErrorBackup = window.onerror @@ -210,4 +211,22 @@ describe('useMeasure', () => { }) ;(window as any).ResizeObserver = RO }) + + it('memoize ref function', () => { + const { result, rerender } = renderHook(() => useMeasure()) + const ref = result.current[0] + rerender() + expect(ref).toBe(result.current[0]) + }) + + it('create new ref function when prop changed', () => { + const { result, rerender } = renderHook(({ scroll }) => useMeasure({ scroll }), { + initialProps: { + scroll: false, + }, + }) + const ref = result.current[0] + rerender({ scroll: true }) + expect(ref).not.toBe(result.current[0]) + }) }) diff --git a/src/web/index.ts b/src/web/index.ts index 6b43339..1468684 100644 --- a/src/web/index.ts +++ b/src/web/index.ts @@ -1,4 +1,4 @@ -import { useEffect, useState, useRef, useMemo } from 'react' +import { useEffect, useState, useRef, useMemo, useCallback, MutableRefObject } from 'react' import { debounce as createDebounce } from 'debounce' declare type ResizeObserverCallback = (entries: any[], observer: ResizeObserver) => void @@ -99,39 +99,17 @@ function useMeasure({ debounce, scroll, polyfill }: Options = { debounce: 0, scr ] }, [set, scrollDebounce, resizeDebounce]) - // cleanup current scroll-listeners / observers - function removeListeners() { - if (state.current.scrollContainers) { - state.current.scrollContainers.forEach((element) => element.removeEventListener('scroll', scrollChange, true)) - state.current.scrollContainers = null - } - - if (state.current.resizeObserver) { - state.current.resizeObserver.disconnect() - state.current.resizeObserver = null - } - } - - // add scroll-listeners / observers - function addListeners() { - if (!state.current.element) return - state.current.resizeObserver = new ResizeObserver(scrollChange) - state.current.resizeObserver!.observe(state.current.element) - if (scroll && state.current.scrollContainers) { - state.current.scrollContainers.forEach((scrollContainer) => - scrollContainer.addEventListener('scroll', scrollChange, { capture: true, passive: true }) - ) - } - } - // the ref we expose to the user - const ref = (node: HTMLOrSVGElement | null) => { - if (!node || node === state.current.element) return - removeListeners() - state.current.element = node - state.current.scrollContainers = findScrollContainers(node) - addListeners() - } + const ref = useCallback( + (node: HTMLOrSVGElement | null) => { + if (!node || node === state.current.element) return + removeListeners(state, scrollChange) + state.current.element = node + state.current.scrollContainers = findScrollContainers(node) + addListeners(state, scrollChange, scroll) + }, + [scroll, scrollChange] + ) // add general event listeners useOnWindowScroll(scrollChange, Boolean(scroll)) @@ -139,12 +117,12 @@ function useMeasure({ debounce, scroll, polyfill }: Options = { debounce: 0, scr // respond to changes that are relevant for the listeners useEffect(() => { - removeListeners() - addListeners() + removeListeners(state, scrollChange) + addListeners(state, scrollChange, scroll) }, [scroll, scrollChange, resizeChange]) // remove all listeners when the components unmounts - useEffect(() => removeListeners, []) + useEffect(() => () => removeListeners(state, scrollChange), []) return [ref, bounds, forceRefresh] } @@ -175,6 +153,31 @@ function findScrollContainers(element: HTMLOrSVGElement | null): HTMLOrSVGElemen return [...result, ...findScrollContainers(element.parentElement)] } +// cleanup current scroll-listeners / observers +function removeListeners(state: MutableRefObject, scrollChange: () => void) { + if (state.current.scrollContainers) { + state.current.scrollContainers.forEach((element) => element.removeEventListener('scroll', scrollChange, true)) + state.current.scrollContainers = null + } + + if (state.current.resizeObserver) { + state.current.resizeObserver.disconnect() + state.current.resizeObserver = null + } +} + +// add scroll-listeners / observers +function addListeners(state: MutableRefObject, scrollChange: () => void, scroll?: boolean) { + if (!state.current.element) return + state.current.resizeObserver = new ResizeObserver(scrollChange) + state.current.resizeObserver!.observe(state.current.element) + if (scroll && state.current.scrollContainers) { + state.current.scrollContainers.forEach((scrollContainer) => + scrollContainer.addEventListener('scroll', scrollChange, { capture: true, passive: true }) + ) + } +} + // Checks if element boundaries are equal const keys: (keyof RectReadOnly)[] = ['x', 'y', 'top', 'bottom', 'left', 'right', 'width', 'height'] const areBoundsEqual = (a: RectReadOnly, b: RectReadOnly): boolean => keys.every((key) => a[key] === b[key]) diff --git a/yarn.lock b/yarn.lock index 08273c5..3f8013b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -931,6 +931,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.5.4": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811" @@ -1015,6 +1022,17 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + "@rollup/plugin-replace@^2.3.2": version "2.3.3" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.3.3.tgz#cd6bae39444de119f5d905322b91ebd4078562e7" @@ -1042,6 +1060,14 @@ dom-accessibility-api "^0.4.5" pretty-format "^25.5.0" +"@testing-library/react-hooks@^3.4.2": + version "3.4.2" + resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-3.4.2.tgz#8deb94f7684e0d896edd84a4c90e5b79a0810bc2" + integrity sha512-RfPG0ckOzUIVeIqlOc1YztKgFW+ON8Y5xaSPbiBkfj9nMkkiLhLeBXT5icfPX65oJV/zCZu4z8EVnUc6GY9C5A== + dependencies: + "@babel/runtime" "^7.5.4" + "@types/testing-library__react-hooks" "^3.4.0" + "@testing-library/react@^10.2.1": version "10.2.1" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.2.1.tgz#f0c5ac9072ad54c29672150943f35d6617263f26" @@ -1070,13 +1096,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/expect@^24.3.0": - version "24.3.0" - resolved "https://registry.yarnpkg.com/@types/expect/-/expect-24.3.0.tgz#d7cab8b3c10c2d92a0cbb31981feceb81d3486f1" - integrity sha512-aq5Z+YFBz5o2b6Sp1jigx5nsmoZMK5Ceurjwy6PZmRv7dEi1jLtkARfvB1ME+OXJUG+7TZUDcv3WoCr/aor6dQ== - dependencies: - expect "*" - "@types/hoist-non-react-statics@*": version "3.3.1" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" @@ -1105,6 +1124,13 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/istanbul-reports@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" + integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/json-schema@^7.0.3": version "7.0.3" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" @@ -1167,6 +1193,13 @@ "@types/prop-types" "*" "@types/react" "*" +"@types/react-test-renderer@*": + version "17.0.0" + resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-17.0.0.tgz#9be47b375eeb906fced37049e67284a438d56620" + integrity sha512-nvw+F81OmyzpyIE1S0xWpLonLUZCMewslPuA8BtjSKc5XEbn8zEQBXS7KuOLHTNnSOEM2Pum50gHOoZ62tqTRg== + dependencies: + "@types/react" "*" + "@types/react@*": version "16.9.11" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.11.tgz#70e0b7ad79058a7842f25ccf2999807076ada120" @@ -1190,10 +1223,10 @@ dependencies: "@types/node" "*" -"@types/stack-utils@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" - integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== +"@types/stack-utils@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" + integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== "@types/styled-components@^5.1.0": version "5.1.0" @@ -1205,6 +1238,13 @@ "@types/react-native" "*" csstype "^2.2.0" +"@types/testing-library__react-hooks@^3.4.0": + version "3.4.1" + resolved "https://registry.yarnpkg.com/@types/testing-library__react-hooks/-/testing-library__react-hooks-3.4.1.tgz#b8d7311c6c1f7db3103e94095fe901f8fef6e433" + integrity sha512-G4JdzEcq61fUyV6wVW9ebHWEiLK2iQvaBuCHHn9eMSbZzVh4Z4wHnUGIvQOYCCYeu5DnUtFyNYuAAgbSaO/43Q== + dependencies: + "@types/react-test-renderer" "*" + "@types/yargs-parser@*": version "13.1.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.1.0.tgz#c563aa192f39350a1d18da36c5a8da382bbd8228" @@ -2620,6 +2660,11 @@ diff-sequences@^26.0.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.0.0.tgz#0760059a5c287637b842bd7085311db7060e88a6" integrity sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg== +diff-sequences@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== + diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -3125,16 +3170,16 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@*, expect@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-26.0.1.tgz#18697b9611a7e2725e20ba3ceadda49bc9865421" - integrity sha512-QcCy4nygHeqmbw564YxNbHTJlXh47dVID2BUP52cZFpLU9zHViMFK6h07cC1wf7GYCTIigTdAXhVua8Yl1FkKg== +expect@^26.0.1: + version "26.6.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" + integrity sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.6.2" ansi-styles "^4.0.0" - jest-get-type "^26.0.0" - jest-matcher-utils "^26.0.1" - jest-message-util "^26.0.1" + jest-get-type "^26.3.0" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" jest-regex-util "^26.0.0" extend-shallow@^2.0.1: @@ -4108,32 +4153,48 @@ jest-diff@^26.0.1: jest-get-type "^26.0.0" pretty-format "^26.0.1" +jest-diff@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + jest-get-type@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039" integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg== -jest-matcher-utils@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.0.1.tgz#12e1fc386fe4f14678f4cc8dbd5ba75a58092911" - integrity sha512-PUMlsLth0Azen8Q2WFTwnSkGh2JZ8FYuwijC8NR47vXKpsrKmA1wWvgcj1CquuVfcYiDEdj985u5Wmg7COEARw== +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== + +jest-matcher-utils@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" + integrity sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw== dependencies: chalk "^4.0.0" - jest-diff "^26.0.1" - jest-get-type "^26.0.0" - pretty-format "^26.0.1" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" -jest-message-util@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.0.1.tgz#07af1b42fc450b4cc8e90e4c9cef11b33ce9b0ac" - integrity sha512-CbK8uQREZ8umUfo8+zgIfEt+W7HAHjQCoRaNs4WxKGhAYBGwEyvxuK81FXa7VeB9pwDEXeeKOB2qcsNVCAvB7Q== +jest-message-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" + integrity sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/types" "^26.0.1" - "@types/stack-utils" "^1.0.1" + "@jest/types" "^26.6.2" + "@types/stack-utils" "^2.0.0" chalk "^4.0.0" graceful-fs "^4.2.4" micromatch "^4.0.2" + pretty-format "^26.6.2" slash "^3.0.0" stack-utils "^2.0.2" @@ -5358,6 +5419,16 @@ pretty-format@^26.0.1: ansi-styles "^4.0.0" react-is "^16.12.0" +pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + pretty-quick@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-2.0.1.tgz#417ee605ade98ecc686e72f63b5d28a2c35b43e9" @@ -5557,11 +5628,34 @@ react-is@^16.12.0, react-is@^16.7.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +"react-is@^16.12.0 || ^17.0.0", react-is@^17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" + integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== + react-is@^16.8.1: version "16.11.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.11.0.tgz#b85dfecd48ad1ce469ff558a882ca8e8313928fa" integrity sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw== +react-shallow-renderer@^16.13.1: + version "16.14.1" + resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz#bf0d02df8a519a558fd9b8215442efa5c840e124" + integrity sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg== + dependencies: + object-assign "^4.1.1" + react-is "^16.12.0 || ^17.0.0" + +react-test-renderer@^17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-17.0.1.tgz#3187e636c3063e6ae498aedf21ecf972721574c7" + integrity sha512-/dRae3mj6aObwkjCcxZPlxDFh73XZLgvwhhyON2haZGUEhiaY5EjfAdw+d/rQmlcFwdTpMXCSGVk374QbCTlrA== + dependencies: + object-assign "^4.1.1" + react-is "^17.0.1" + react-shallow-renderer "^16.13.1" + scheduler "^0.20.1" + react@^16.11.0: version "16.11.0" resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb" @@ -5938,6 +6032,14 @@ scheduler@^0.17.0: loose-envify "^1.1.0" object-assign "^4.1.1" +scheduler@^0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.1.tgz#da0b907e24026b01181ecbc75efdc7f27b5a000c" + integrity sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"