Skip to content

Commit

Permalink
React router [email protected] fixes (#1214)
Browse files Browse the repository at this point in the history
* Specify `ContextRouter` as an exact object

Our type signature should not assume that additional keys may be present in this object.

* withRouter uses type spread notation, instead of intersection

intersection of inexact object types behaves much like spreading, but when both objects are exact, the intersection type becomes an empty set.

See: facebook/flow#2626

* Upgrade babel-eslint version in definitions/ to match cli

* Tests use spread notation instead of intersection
  • Loading branch information
duyitc authored and marudor committed Sep 8, 2017
1 parent 8787be9 commit ab65ebf
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 885 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import * as React from "react";

declare module "react-router-dom" {
declare export class BrowserRouter extends React$Component<{
basename?: string,
Expand Down Expand Up @@ -81,11 +79,11 @@ declare module "react-router-dom" {
url: string
};

declare export type ContextRouter = {
declare export type ContextRouter = {|
history: RouterHistory,
location: Location,
match: Match
};
|};

declare export type GetUserConfirmation = (
message: string,
Expand Down Expand Up @@ -129,7 +127,7 @@ declare module "react-router-dom" {
declare export class Route extends React$Component<{
component?: React$ComponentType<*>,
render?: (router: ContextRouter) => React$Node,
children?: React.ComponentType<ContextRouter>,
children?: React$ComponentType<ContextRouter>,
path?: string,
exact?: boolean,
strict?: boolean
Expand All @@ -140,7 +138,7 @@ declare module "react-router-dom" {
}> {}

declare export function withRouter<P>(
Component: React$ComponentType<ContextRouter & P>
Component: React$ComponentType<{| ...ContextRouter, ...P |}>
): React$ComponentType<P>;

declare type MatchPathOptions = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// @flow
import React from "react";
import {
BrowserRouter,
HashRouter,
Link,
NavLink,
matchPath,
withRouter,
type ContextRouter,
type Match
withRouter
} from "react-router-dom";
import type { ContextRouter, Match } from "react-router-dom";

// BrowserRouter
<BrowserRouter>
Expand Down Expand Up @@ -106,14 +106,21 @@ const matchError: string = matchPath("/the/pathname", {
path: "the/:dynamicId"
});

const Unrouted: React$ComponentType<
ContextRouter & {| someProp: string |}
> = () => <span />;
const Unrouted: React$ComponentType<{|
...ContextRouter,
someProp: string
|}> = () => <span />;

const Routed1: React$ComponentType<{| someProp: string |}> = withRouter(
Unrouted
);
// $ExpectError

// $ExpectError: This error bubbles up from the assignment in Routed2.
const Unrouted2: React$ComponentType<{|
...ContextRouter,
someProp: string
|}> = () => <span />;

const Routed2: React$ComponentType<{| someProp2: string |}> = withRouter(
Unrouted
Unrouted2
);
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,20 @@ declare module "react-router" {
url: string
};

declare export type ContextRouter = {
declare export type ContextRouter = {|
history: RouterHistory,
location: Location,
match: Match
};
|};

declare export type GetUserConfirmation = (
message: string,
callback: (confirmed: boolean) => void
) => void;

declare type StaticRouterContext = {
declare type StaticRouterContext = {|
url?: string
};
|};

declare export class StaticRouter extends React$Component<{
basename?: string,
Expand Down Expand Up @@ -106,7 +106,7 @@ declare module "react-router" {
}> {}

declare export function withRouter<P>(
Component: React$ComponentType<ContextRouter & P>
Component: React$ComponentType<{| ...ContextRouter, ...P |}>
): React$ComponentType<P>;

declare type MatchPathOptions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import {
withRouter,
matchPath
} from "react-router";
import type { Location, Match, ContextRouter } from "react-router";
import type {
Location,
Match,
ContextRouter,
RouterHistory
} from "react-router";

// Location
var locationOK: Location = {
Expand Down Expand Up @@ -55,9 +60,10 @@ var locationError: Location = {};
// $ExpectError
<MemoryRouter initialEntries={""} />;

// Router - fails as history is void in Flow 0.53
// var history: History;
// <Router history={history}><div /></Router>;
declare var history: RouterHistory;
<Router history={history}>
<div />
</Router>;
// $ExpectError
<Router>
Expand Down Expand Up @@ -110,10 +116,10 @@ var User = () => <div />;
</Switch>;

// withRouter
type FooProps = ContextRouter & {
location: Location,
type FooProps = {|
...ContextRouter,
name: string
};
|};
const Foo = ({ location, name }: FooProps) =>
<div>
{location.pathname} {name}
Expand All @@ -135,9 +141,9 @@ withRouter("nope");
const BarWithRouterError = withRouter(Bar);
<BarWithRouterError name={3} />;

// $ExpectError
const IncorrectHistoryUsage = ({ history, name }: Foo2Props) => {
// Wrong arguments here, error will bubble up to the component declaration
const IncorrectHistoryUsage = ({ history, name }: FooProps) => {
// Wrong arguments here
// $ExpectError
history.push(["bla"]);
return (
<div>
Expand All @@ -160,14 +166,21 @@ matchPath();
// $ExpectError
const matchError: string = matchPath("/the/pathname", "the/:dynamicId");

const Unrouted: React$ComponentType<
ContextRouter & {| someProp: string |}
> = () => <span />;
const Unrouted: React$ComponentType<{|
...ContextRouter,
someProp: string
|}> = () => <span />;

const Routed1: React$ComponentType<{| someProp: string |}> = withRouter(
Unrouted
);
// $ExpectError

// $ExpectError: This error bubbles up from the assignment in Routed2.
const Unrouted2: React$ComponentType<{|
...ContextRouter,
someProp: string
|}> = () => <span />;

const Routed2: React$ComponentType<{| someProp2: string |}> = withRouter(
Unrouted
Unrouted2
);
Loading

0 comments on commit ab65ebf

Please sign in to comment.