From d934b430e238b2d99881f85c95d41324393beb7f Mon Sep 17 00:00:00 2001 From: David Epely Date: Wed, 15 Mar 2023 15:54:15 +0100 Subject: [PATCH 1/3] Fix runTests command for flow@^0.200.0 set `exact_by_default` option (#4423) from 0.200.0, `exact_by_default` option is required in flowconfig and from 0.202.0, this option is `true` by default cf. https://flow.org/en/docs/config/options/#toc-exact-by-default-boolean --- cli/src/commands/runTests.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cli/src/commands/runTests.js b/cli/src/commands/runTests.js index ef32bc728f..824f5ba0fd 100644 --- a/cli/src/commands/runTests.js +++ b/cli/src/commands/runTests.js @@ -319,6 +319,7 @@ async function writeFlowConfig(repoDirPath, testDirPath, libDefPath, version) { '[options]', 'include_warnings=true', 'server.max_workers=0', + semver.gte(version, '0.200.0') ? 'exact_by_default=true' : '', // from version 0.202.0 default is true // Fixes out of shared memory error for Mac Rosetta 2, see https://github.com/facebook/flow/issues/8538 'sharedmemory.heap_size=3221225472', semver.lt(version, '0.125.0') @@ -478,6 +479,7 @@ async function removeTrashFromBinDir() { const CONFIGURATION_CHANGE_VERSIONS = [ 'v0.104.0', // Adding lint 'v0.125.0', // Remove suppress_comments + 'v0.200.0', // exact_by_default become required ]; // This function splits a list of flow versions into a list of lists of versions From 48815e6b8ae4c1a12550668c9894ba8092ae324b Mon Sep 17 00:00:00 2001 From: David Epely Date: Wed, 15 Mar 2023 20:17:36 +0100 Subject: [PATCH 2/3] [react-router-dom] fix test after migrating flow to ^0.200.0 (#4424) also improve test saying testing `useOutlet` and test `useOutletContext` --- .../flow_v0.104.x-/react-router-dom_v6.x.x.js | 2 +- .../flow_v0.104.x-/test_react-router-dom.js | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/react-router-dom_v6.x.x.js b/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/react-router-dom_v6.x.x.js index c4f597ce4d..901c2fdc36 100644 --- a/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/react-router-dom_v6.x.x.js +++ b/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/react-router-dom_v6.x.x.js @@ -441,7 +441,7 @@ declare module "react-router-dom" { declare export function useHistory(): $PropertyType; declare export function useLocation(): $PropertyType; - declare export function useOutletContext(): T; + declare export function useOutletContext(): T; declare export function useParams, 'params'>>(): Params; declare export function useRouteMatch(path?: MatchPathOptions | string | string[]): $PropertyType; diff --git a/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/test_react-router-dom.js b/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/test_react-router-dom.js index e99567a96e..02273f48bd 100644 --- a/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/test_react-router-dom.js +++ b/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/test_react-router-dom.js @@ -14,6 +14,7 @@ import { useHistory, useLocation, useNavigate, + useOutlet, useOutletContext, useParams, useRouteMatch, @@ -496,12 +497,34 @@ describe("react-router-dom", () => { }); it('useOutlet', () => { + useOutlet() + + const Component = () =>
Hi!
; + + useOutlet() + + // $FlowExpectedError[extra-arg] + useOutlet('') + }) + + it('useOutletContext', () => { const [count, setCount] = useOutletContext(); const increment = () => setCount((c) => c + 1); ; // $FlowExpectedError[extra-arg] useOutletContext(''); + + const t1: number = useOutletContext(); + + type Tuple = [string, (foo: string) => void]; + + const [foo, setFoo] = useOutletContext(); + (foo: string); + (setFoo: (foo: string) => void); + + // $FlowExpectedError[incompatible-type] + const t2: string = useOutletContext(); }); it('useParams', () => { From 1ec13c5c01dd75a340830314c101d77168551858 Mon Sep 17 00:00:00 2001 From: David Epely Date: Thu, 16 Mar 2023 22:12:23 +0100 Subject: [PATCH 3/3] [react-router-dom] navlink, renderMatches & matchRoutes (#4425) * [react-router-dom] drop outdated support of Navlink props `activeClassName` & `activeStyle` also improve type className & style then add tests cf. https://reactrouter.com/en/main/upgrading/v5#remove-activeclassname-and-activestyle-props-from-navlink- * [react-router-dom] Navlink prop `exact` renamed to `end` cf. https://reactrouter.com/en/main/upgrading/v5#rename-navlink-exact-to-navlink-end * [react-router-dom] Navlink's `isActive` prop has been removed `isActive` has been removed between versions 5 & 6 without notice: v5: https://v5.reactrouter.com/web/api/NavLink/isactive-func latest: https://reactrouter.com/en/main/components/nav-link#navlink * [react-router-dom] Navlink accepts render prop cf. https://reactrouter.com/en/main/components/nav-link#children * [react-router-dom] refactor `renderMatches` & `matchRoutes` types improve types to make it more precise and more close to typescript definition cf. matchRoute https://github.com/remix-run/react-router/blob/d19c2c221c9f53b8273033f31b0ee94734719f47/packages/router/utils.ts#L374 renderRoutes https://github.com/remix-run/react-router/blob/d19c2c221c9f53b8273033f31b0ee94734719f47/packages/react-router/lib/components.tsx#L630 --- .../flow_v0.104.x-/react-router-dom_v6.x.x.js | 30 +++--- .../flow_v0.104.x-/test_react-router-dom.js | 99 ++++++++++++++++++- 2 files changed, 106 insertions(+), 23 deletions(-) diff --git a/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/react-router-dom_v6.x.x.js b/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/react-router-dom_v6.x.x.js index 901c2fdc36..2550daaa72 100644 --- a/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/react-router-dom_v6.x.x.js +++ b/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/react-router-dom_v6.x.x.js @@ -24,13 +24,10 @@ declare module "react-router-dom" { declare export var NavLink: React$ComponentType<{ +to: string | LocationShape, - +activeClassName?: string, - +className?: string, - +activeStyle?: { +[string]: mixed, ... }, - +style?: { +[string]: mixed, ... }, - +isActive?: (match: Match, location: Location) => boolean, - +children?: React$Node, - +exact?: boolean, + +className?: string | (props: {| isActive: boolean, isPending: boolean |}) => string | void, + +style?: { +[string]: mixed, ... } | (props: {| isActive: boolean, isPending: boolean|}) => { +[string]: mixed, ... } | void, + +children?: React$Node | ({| isActive: boolean, isPending: boolean |}) => React$Node, + +end?: boolean, +strict?: boolean, ... }> @@ -464,28 +461,23 @@ declare module "react-router-dom" { declare export type RouteObject = IndexRouteObject | NonIndexRouteObject; - declare export function createRoutesFromChildren( - children: React$Node, - ): Array; + declare export function createRoutesFromElements(elements: React$Node): RouteObject[] + declare export var createRoutesFromChildren: typeof createRoutesFromElements; declare export type Params = { +[key: Key]: string | void; }; - declare type RouteMatch = {| - params: Params, - pathname: string, - route: RouteObject, - |}; + declare export type RouteMatch = AgnosticRouteMatch - declare export function matchRoutes( + declare export function matchRoutes( routes: Array, location: LocationShape | string, basename?: string, - ): Array> | null; + ): Array> | null; - declare export function renderMatches( - matches: Array> | null, + declare export function renderMatches( + matches: Array> | null, ): React$Element | null; declare type PathPattern = {| diff --git a/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/test_react-router-dom.js b/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/test_react-router-dom.js index 02273f48bd..ca39ee3cc5 100644 --- a/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/test_react-router-dom.js +++ b/definitions/npm/react-router-dom_v6.x.x/flow_v0.104.x-/test_react-router-dom.js @@ -6,6 +6,8 @@ import { Link, NavLink, matchPath, + matchRoutes, + renderMatches, withRouter, Navigate, Outlet, @@ -21,6 +23,8 @@ import { useMatches, } from "react-router-dom"; import type { + AgnosticRouteMatch, + RouteObject, Location, ContextRouter, Match, @@ -122,13 +126,10 @@ describe("react-router-dom", () => { true} strict - exact + end > About ; @@ -164,6 +165,44 @@ describe("react-router-dom", () => { // $FlowExpectedError[incompatible-type] - to prop must be a string or LocationShape ; + + // activeClassName, activeStyle, end, isActive have been dropped unfortunately props cannot be strict so no errors can be expected + true} + end + > + About + ; + }); + + it('supports enhanced className & style props', () => { + + isPending ? "pending" : isActive ? "active" : undefined + } + style={({ isActive, isPending}) => + isPending ? { color: "red" } : isActive ? { color: "blue" } : undefined + } + > + About + ; + + // $FlowExpectedError[incompatible-type] + ; + // $FlowExpectedError[incompatible-type] + ; + }); + + it('supports render prop as children', () => { + + {({ isActive, isPending }) => ( + Tasks + )} + }); }); @@ -198,6 +237,58 @@ describe("react-router-dom", () => { }); }); + describe('renderMatches', () => { + it('works', () => { + renderMatches([]); + + renderMatches([]); + + const contentWithEmptyMatches: null|React$Element = renderMatches([]); + + const contentWithMatches: null|React$Element = renderMatches([{ + params: {}, + pathname: '/', + pathnameBase: '', + route: { + index: false, + children: [{ + index: true, + }], + }, + }]); + }); + + it('raises', () => { + // $FlowExpectedError[incompatible-call] + renderMatches(5); + + // $FlowExpectedError[incompatible-type] + const contentWithEmptyMatches: number = renderMatches([]); + }); + }); + + describe('matchRoutes', () => { + it('works', () => { + matchRoutes([], '/'); + + matchRoutes([], '/'); + + const contentWithEmptyMatches: Array> | null = matchRoutes([], '/'); + + const contentWithMatches: Array> | null = matchRoutes([{ + id: 'bar', + path: 'bar', + index: false, + children: [], + }], '/'); + }); + + it('raises an error with invalid arguments', () => { + // $FlowExpectedError[incompatible-call] + matchRoutes(5, '/'); + }); + }); + describe("withRouter", () => { type Props = { history: RouterHistory,