43 | ,
44 | node
45 | );
46 | }).not.toThrow();
47 | });
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/website/modules/docs/Core.js:
--------------------------------------------------------------------------------
1 | export default {
2 | api: [
3 | require("../../../packages/react-router/docs/api/hooks.md"),
4 | require("../../../packages/react-router/docs/api/MemoryRouter.md"),
5 | require("../../../packages/react-router/docs/api/Prompt.md"),
6 | require("../../../packages/react-router/docs/api/Redirect.md"),
7 | require("../../../packages/react-router/docs/api/Route.md"),
8 | require("../../../packages/react-router/docs/api/Router.md"),
9 | require("../../../packages/react-router/docs/api/StaticRouter.md"),
10 | require("../../../packages/react-router/docs/api/Switch.md"),
11 | require("../../../packages/react-router/docs/api/history.md"),
12 | require("../../../packages/react-router/docs/api/location.md"),
13 | require("../../../packages/react-router/docs/api/match.md"),
14 | require("../../../packages/react-router/docs/api/withRouter.md"),
15 | require("../../../packages/react-router/docs/api/generatePath.md")
16 | ],
17 |
18 | examples: [],
19 |
20 | guides: [
21 | require("../../../packages/react-router/docs/guides/philosophy.md"),
22 | require("../../../packages/react-router/docs/guides/quick-start.md"),
23 | require("../../../packages/react-router/docs/guides/testing.md"),
24 | require("../../../packages/react-router/docs/guides/redux.md"),
25 | require("../../../packages/react-router/docs/guides/static-routes.md")
26 | ]
27 | };
28 |
--------------------------------------------------------------------------------
/packages/react-router-dom/examples/URLParams.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | BrowserRouter as Router,
4 | Switch,
5 | Route,
6 | Link,
7 | useParams
8 | } from "react-router-dom";
9 |
10 | // Params are placeholders in the URL that begin
11 | // with a colon, like the `:id` param defined in
12 | // the route in this example. A similar convention
13 | // is used for matching dynamic segments in other
14 | // popular web frameworks like Rails and Express.
15 |
16 | export default function ParamsExample() {
17 | return (
18 |
19 |
20 |
Accounts
21 |
22 |
23 |
24 | Netflix
25 |
26 |
27 | Zillow Group
28 |
29 |
30 | Yahoo
31 |
32 |
33 | Modus Create
34 |
35 |
36 |
37 |
38 | } />
39 |
40 |
41 |
42 | );
43 | }
44 |
45 | function Child() {
46 | // We can use the `useParams` hook here to access
47 | // the dynamic pieces of the URL.
48 | let { id } = useParams();
49 |
50 | return (
51 |
52 |
ID: {id}
53 |
54 | );
55 | }
56 |
--------------------------------------------------------------------------------
/packages/react-router/modules/withRouter.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import hoistStatics from "hoist-non-react-statics";
4 | import invariant from "tiny-invariant";
5 |
6 | import RouterContext from "./RouterContext.js";
7 |
8 | /**
9 | * A public higher-order component to access the imperative API
10 | */
11 | function withRouter(Component) {
12 | const displayName = `withRouter(${Component.displayName || Component.name})`;
13 | const C = props => {
14 | const { wrappedComponentRef, ...remainingProps } = props;
15 |
16 | return (
17 |
18 | {context => {
19 | invariant(
20 | context,
21 | `You should not use <${displayName} /> outside a `
22 | );
23 | return (
24 |
29 | );
30 | }}
31 |
32 | );
33 | };
34 |
35 | C.displayName = displayName;
36 | C.WrappedComponent = Component;
37 |
38 | if (__DEV__) {
39 | C.propTypes = {
40 | wrappedComponentRef: PropTypes.oneOfType([
41 | PropTypes.string,
42 | PropTypes.func,
43 | PropTypes.object
44 | ])
45 | };
46 | }
47 |
48 | return hoistStatics(C, Component);
49 | }
50 |
51 | export default withRouter;
52 |
--------------------------------------------------------------------------------
/packages/react-router/modules/hooks.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import invariant from "tiny-invariant";
3 |
4 | import Context from "./RouterContext.js";
5 | import matchPath from "./matchPath.js";
6 |
7 | const useContext = React.useContext;
8 |
9 | export function useHistory() {
10 | if (__DEV__) {
11 | invariant(
12 | typeof useContext === "function",
13 | "You must use React >= 16.8 in order to use useHistory()"
14 | );
15 | }
16 |
17 | return useContext(Context).history;
18 | }
19 |
20 | export function useLocation() {
21 | if (__DEV__) {
22 | invariant(
23 | typeof useContext === "function",
24 | "You must use React >= 16.8 in order to use useLocation()"
25 | );
26 | }
27 |
28 | return useContext(Context).location;
29 | }
30 |
31 | export function useParams() {
32 | if (__DEV__) {
33 | invariant(
34 | typeof useContext === "function",
35 | "You must use React >= 16.8 in order to use useParams()"
36 | );
37 | }
38 |
39 | const match = useContext(Context).match;
40 | return match ? match.params : {};
41 | }
42 |
43 | export function useRouteMatch(path) {
44 | if (__DEV__) {
45 | invariant(
46 | typeof useContext === "function",
47 | "You must use React >= 16.8 in order to use useRouteMatch()"
48 | );
49 | }
50 |
51 | const location = useLocation();
52 | const match = useContext(Context).match;
53 |
54 | return path ? matchPath(location.pathname, path) : match;
55 | }
56 |
--------------------------------------------------------------------------------
/website/modules/components/API.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import { Redirect } from "react-router-dom";
3 | import { Block } from "jsxstyle";
4 | import PropTypes from "prop-types";
5 |
6 | import ScrollToDoc from "./ScrollToDoc.js";
7 | import MarkdownViewer from "./MarkdownViewer.js";
8 |
9 | // nearly identical to Guide, haven't taken the time to abstact cause I'm not sure it'll
10 | // remain so identical ... maybe it will?
11 | export default class API extends Component {
12 | static propTypes = {
13 | match: PropTypes.object,
14 | data: PropTypes.object
15 | };
16 |
17 | render() {
18 | const { match, data } = this.props;
19 | const {
20 | params: { mod, header: headerParam, environment }
21 | } = match;
22 | const doc = mod && data.api.find(doc => mod === doc.title.slug);
23 | const header =
24 | doc && headerParam ? doc.headers.find(h => h.slug === headerParam) : null;
25 | return (
26 |
27 |
28 |
29 | {data.api.map((d, i) => (
30 |
31 | ))}
32 |
33 | {mod && !doc && }
34 | {headerParam && doc && !header && (
35 |
36 | )}
37 |
38 | );
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/packages/react-router-native/examples/Recursive.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { StyleSheet, Text, ScrollView } from "react-native";
3 |
4 | import { NativeRouter, Route, Link } from "react-router-native";
5 |
6 | const PEEPS = [
7 | { id: 0, name: "Michelle", friends: [1, 2, 3] },
8 | { id: 1, name: "Sean", friends: [0, 3] },
9 | { id: 2, name: "Kim", friends: [0, 1, 3] },
10 | { id: 3, name: "David", friends: [1, 2] }
11 | ];
12 |
13 | const find = id => PEEPS.find(p => p.id === id);
14 |
15 | function Person({ match }) {
16 | const person = find(match.params.id);
17 |
18 | return (
19 |
20 |
21 | {person.name}
22 | ’s Friends
23 |
24 | {person.friends.map(id => (
25 |
31 | {find(id).name}
32 |
33 | ))}
34 |
35 |
36 | );
37 | }
38 |
39 | function App() {
40 | return (
41 |
42 |
43 |
44 | );
45 | }
46 |
47 | const styles = StyleSheet.create({
48 | container: {
49 | marginTop: 25,
50 | padding: 10
51 | },
52 | header: {
53 | fontSize: 20
54 | }
55 | });
56 |
57 | export default App;
58 |
--------------------------------------------------------------------------------
/packages/react-router-dom/examples/CustomLink.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | BrowserRouter as Router,
4 | Switch,
5 | Route,
6 | Link,
7 | useRouteMatch
8 | } from "react-router-dom";
9 |
10 | // This example show how you could create a custom
11 | // that renders something special when the URL
12 | // is the same as the one the points to.
13 |
14 | export default function CustomLinkExample() {
15 | return (
16 |
17 |
66 | The name in the query string is "{name}
67 | "
68 |
69 | ) : (
70 |
There is no name in the query string
71 | )}
72 |
73 | );
74 | }
75 |
--------------------------------------------------------------------------------
/packages/react-router/docs/guides/Installation.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | React Router runs in multiple environments: browsers, servers, native, and even VR (works in the dev preview!) While many components are shared (like `Route`) others are specific to environment (like `NativeRouter`). Rather than requiring you install two packages, you only have to install the package for the target environment. Any shared components between the environments are re-exported from the environment specific package.
4 |
5 | ## Web
6 |
7 | ```bash
8 | npm install react-router-dom
9 | # or
10 | yarn add react-router-dom
11 | ```
12 |
13 | All of the package modules can be imported from the top:
14 |
15 | ```js
16 | import {
17 | BrowserRouter as Router,
18 | StaticRouter, // for server rendering
19 | Route,
20 | Link
21 | // etc.
22 | } from "react-router-dom";
23 | ```
24 |
25 | ## Native
26 |
27 | We're still working on great documentation for the native capabilities of React Router. For now we recommend you [read the source](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-native).
28 |
29 | ```bash
30 | yarn add react-router-native
31 | # or if not using the react-native cli
32 | npm install react-router-native
33 | ```
34 |
35 | All of the package modules can be imported from the top:
36 |
37 | ```js
38 | import {
39 | NativeRouter as Router,
40 | DeepLinking,
41 | BackButton,
42 | Link,
43 | Route
44 | // etc.
45 | } from "react-router-native";
46 | ```
47 |
48 | ## Who-knows-where
49 |
50 | ```bash
51 | yarn add react-router
52 | # or if not using the react-native cli
53 | npm install react-router
54 | ```
55 |
56 | All of the package modules can be imported from the top:
57 |
58 | ```js
59 | import {
60 | MemoryRouter as Router,
61 | Route
62 | // etc.
63 | } from "react-router";
64 | ```
65 |
66 | You can use React Router's navigation anywhere you run React, the navigation state is kept in a memory router. You can look at the implementation of `NativeRouter` to get an idea on how to integrate.
67 |
--------------------------------------------------------------------------------
/packages/react-router-dom/examples/NoMatch.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | BrowserRouter as Router,
4 | Route,
5 | Link,
6 | Switch,
7 | Redirect,
8 | useLocation
9 | } from "react-router-dom";
10 |
11 | // You can use the last in a as a kind of
12 | // "fallback" route, to catch 404 errors.
13 | //
14 | // There are a few useful things to note about this example:
15 | //
16 | // - A renders the first child that matches
17 | // - A may be used to redirect old URLs to new ones
18 | // - A Home
27 |
28 |
78 | );
79 | }
80 |
--------------------------------------------------------------------------------
/website/webpack/prismjs-loader.js:
--------------------------------------------------------------------------------
1 | /*
2 | * modified version of https://github.com/valor-software/prismjs-loader
3 | *
4 | * The MIT License (MIT)
5 | *
6 | * Copyright (c) 2015-2016 Valor Software
7 | * Copyright (c) 2015-2016 Dmitriy Shekhovtsov
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in all
17 | * copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 | * SOFTWARE.
26 | */
27 |
28 | "use strict";
29 | const Prism = require("prismjs");
30 |
31 | module.exports = function loader(content) {
32 | const query = this.query;
33 |
34 | if (!query.lang) {
35 | throw new Error("You need to provide `lang` query parameter");
36 | }
37 |
38 | if (!Prism.languages[query.lang]) {
39 | /* eslint-disable */
40 | require(`prismjs/components/prism-${query.lang}.js`);
41 | /* eslint-enable */
42 | }
43 |
44 | const lang = Prism.languages[query.lang];
45 |
46 | const value = Prism.highlight(content, lang);
47 | const str = JSON.stringify(value);
48 |
49 | return `module.exports = ${str}`;
50 | };
51 |
52 | module.exports.seperable = true;
53 |
--------------------------------------------------------------------------------
/packages/react-router-dom/examples/PreventingTransitions.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | BrowserRouter as Router,
4 | Switch,
5 | Route,
6 | Link,
7 | Prompt
8 | } from "react-router-dom";
9 |
10 | // Sometimes you want to prevent the user from
11 | // navigating away from a page. The most common
12 | // use case is when they have entered some data
13 | // into a form but haven't submitted it yet, and
14 | // you don't want them to lose it.
15 |
16 | export default function PreventingTransitionsExample() {
17 | return (
18 |
19 |
20 |
21 | Form
22 |
23 |
24 | One
25 |
26 |
27 | Two
28 |
29 |
30 |
31 |
32 | } />
33 | One} />
34 | Two} />
35 |
36 |
37 | );
38 | }
39 |
40 | function BlockingForm() {
41 | let [isBlocking, setIsBlocking] = useState(false);
42 |
43 | return (
44 |
77 | );
78 | }
79 |
--------------------------------------------------------------------------------
/packages/react-router/modules/__tests__/Route-context-test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import { createMemoryHistory as createHistory } from "history";
4 | import { Route, Router, __RouterContext as RouterContext } from "react-router";
5 |
6 | import renderStrict from "./utils/renderStrict.js";
7 |
8 | describe("A ", () => {
9 | const node = document.createElement("div");
10 |
11 | afterEach(() => {
12 | ReactDOM.unmountComponentAtNode(node);
13 | });
14 |
15 | describe("context", () => {
16 | let context;
17 | function ContextChecker() {
18 | return (
19 |
20 | {value => {
21 | context = value;
22 | return null;
23 | }}
24 |
25 | );
26 | }
27 |
28 | afterEach(() => {
29 | context = undefined;
30 | });
31 |
32 | it("has a `history` property", () => {
33 | const history = createHistory();
34 |
35 | renderStrict(
36 |
37 |
38 | ,
39 | node
40 | );
41 |
42 | expect(context.history).toBe(history);
43 | });
44 |
45 | it("has a `location` property", () => {
46 | const history = createHistory();
47 |
48 | renderStrict(
49 |
50 |
51 | ,
52 | node
53 | );
54 |
55 | expect(context.location).toBe(history.location);
56 | });
57 |
58 | it("has a `match` property", () => {
59 | const history = createHistory({
60 | initialEntries: ["/"]
61 | });
62 |
63 | renderStrict(
64 |
65 |
66 | ,
67 | node
68 | );
69 |
70 | expect(context.match).toMatchObject({
71 | path: "/",
72 | url: "/",
73 | params: {},
74 | isExact: true
75 | });
76 | });
77 | });
78 | });
79 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js: node
3 | cache: yarn
4 | jobs:
5 | include:
6 | - stage: Test
7 | env: TEST_ENV=source
8 | before_script:
9 | # react-router CJS build is imported by react-router-config tests,
10 | # so we need to build it before running react-router-config tests
11 | - cd packages/react-router && BUILD_ENV=cjs yarn build && cd -
12 | script: yarn test
13 | - env: TEST_ENV=cjs BUILD_ENV=cjs
14 | before_script: yarn build
15 | script: yarn test
16 | - env: TEST_ENV=umd BUILD_ENV=umd
17 | before_script:
18 | # react-router ESM build is imported by react-router-dom UMD,
19 | # so we need to build it before building react-router-dom UMD
20 | - cd packages/react-router && BUILD_ENV=esm yarn build && cd -
21 | - yarn build
22 | # react-router CJS build is imported by react-router-config tests,
23 | # so we need to build it before running react-router-config tests
24 | - cd packages/react-router && BUILD_ENV=cjs yarn build && cd -
25 | script: yarn test
26 | - stage: Release
27 | if: tag =~ ^v[0-9]
28 | before_script: yarn build
29 | script: echo "Publishing $TRAVIS_TAG to npm ..."
30 | before_deploy: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > "$HOME/.npmrc"
31 | deploy:
32 | provider: script
33 | skip_cleanup: true
34 | script: lerna publish from-git --yes --pre-dist-tag next
35 | on:
36 | tags: true
37 | - stage: Deploy Website
38 | if: branch = website
39 | env: PUBLIC_PATH=/react-router/
40 | before_script: yarn build
41 | script: echo "Deploying website to https://reacttraining.com$PUBLIC_PATH"
42 | before_deploy:
43 | - openssl aes-256-cbc -K $encrypted_70c5e56b421c_key -iv $encrypted_70c5e56b421c_iv
44 | -in website-deploy-key.enc -out website-deploy-key -d
45 | - chmod 600 website-deploy-key
46 | - eval $(ssh-agent -s)
47 | - ssh-add website-deploy-key
48 | deploy:
49 | provider: script
50 | script: bash scripts/deploy-website.sh
51 | skip_cleanup: true
52 | on:
53 | branch: website
54 |
--------------------------------------------------------------------------------
/packages/react-router-dom/docs/api/BrowserRouter.md:
--------------------------------------------------------------------------------
1 | # <BrowserRouter>
2 |
3 | A [``](../../../react-router/docs/api/Router.md) that uses the HTML5 history API (`pushState`, `replaceState` and the `popstate` event) to keep your UI in sync with the URL.
4 |
5 | ```jsx
6 |
12 |
13 |
14 | ```
15 |
16 | ## basename: string
17 |
18 | The base URL for all locations. If your app is served from a sub-directory on your server, you'll want to set this to the sub-directory. A properly formatted basename should have a leading slash, but no trailing slash.
19 |
20 | ```jsx
21 |
22 | // renders
23 | ```
24 |
25 | ## getUserConfirmation: func
26 |
27 | A function to use to confirm navigation. Defaults to using [`window.confirm`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm).
28 |
29 | ```jsx
30 | {
32 | // this is the default behavior
33 | const allowTransition = window.confirm(message);
34 | callback(allowTransition);
35 | }}
36 | />
37 | ```
38 |
39 | ## forceRefresh: bool
40 |
41 | If `true` the router will use full page refreshes on page navigation. You may want to use this to imitate the way a traditional server-rendered app would work with full page refreshes between page navigation.
42 |
43 | ```jsx
44 |
45 | ```
46 |
47 | ## keyLength: number
48 |
49 | The length of `location.key`. Defaults to 6.
50 |
51 | ```jsx
52 |
53 | ```
54 |
55 | ## children: node
56 |
57 | The child elements to render.
58 |
59 | Note: On React < 16 you must use a [single child element](https://facebook.github.io/react/docs/react-api.html#reactchildrenonly) since a render method cannot return more than one element. If you need more than one element, you might try wrapping them in an extra `