{"_id":"@arthurdandrea/found","_rev":"2-260e84041351d4d1abb1905648654188","name":"@arthurdandrea/found","dist-tags":{"latest":"0.5.3"},"versions":{"0.4.9":{"name":"@arthurdandrea/found","version":"0.4.9","description":"Extensible route-based routing for React applications","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"babel src -d lib --delete-dir-on-start && cpy types/*.d.ts lib && cpy types/server/*.d.ts lib/server","format":"eslint --fix . && npm run prettier -- --write","lint":"eslint . && npm run prettier -- -l","prepublish":"npm run build","prettier":"prettier --ignore-path .eslintignore '**/*.{md,ts,tsx}'","tdd":"jest --watch","test":"npm run lint && npm run test:ts && npm run testonly -- --coverage","test:ts":"dtslint types","testonly":"jest --runInBand --verbose"},"husky":{"hooks":{"pre-commit":"lint-staged"}},"lint-staged":{"*.js":["eslint --fix","git add"],"*.{md,ts,tsx}":["prettier --write","git add"],"/README.md":["doctoc","git add"]},"prettier":{"printWidth":79,"singleQuote":true,"trailingComma":"all"},"jest":{"collectCoverageFrom":["src/**"],"resetMocks":true,"restoreMocks":true,"setupFiles":["<rootDir>/test/setup.js"],"testPathIgnorePatterns":["/node_modules/","<rootDir>/types/"]},"repository":{"type":"git","url":"git+https://github.com/4Catalyzer/found.git"},"keywords":["react","router","routes","routing"],"author":{"name":"4Catalyzer"},"license":"MIT","bugs":{"url":"https://github.com/4Catalyzer/found/issues"},"homepage":"https://github.com/4Catalyzer/found#readme","dependencies":{"@babel/runtime-corejs3":"^7.6.2","@restart/context":"^2.1.4","farce":"^0.2.8","invariant":"^2.2.4","is-promise":"^2.1.0","lodash":"^4.17.15","path-to-regexp":"^1.7.0","prop-types":"^15.7.2","react-redux":"^7.0.0","react-static-container":"^1.0.2","redux":"^4.0.4","warning":"^4.0.3"},"peerDependencies":{"react":">=16.8.0"},"devDependencies":{"@4c/babel-preset":"^7.0.0","@babel/cli":"^7.6.2","@babel/core":"^7.6.2","@types/react":"^16.9.5","@types/react-dom":"^16.9.1","babel-jest":"^24.9.0","babel-plugin-add-module-exports":"^1.0.2","codecov":"^3.6.1","cpy-cli":"^2.0.0","delay":"^4.3.0","doctoc":"^1.4.0","dtslint":"^0.9.8","enzyme":"^3.10.0","enzyme-adapter-react-16":"^1.14.0","eslint":"^6.5.1","eslint-config-4catalyzer-jest":"^2.0.1","eslint-config-4catalyzer-react":"^1.0.0","eslint-config-prettier":"^6.3.0","eslint-plugin-import":"^2.18.2","eslint-plugin-jest":"^22.17.0","eslint-plugin-jsx-a11y":"^6.2.3","eslint-plugin-prettier":"^3.1.1","eslint-plugin-react":"^7.16.0","eslint-plugin-react-hooks":"^2.1.2","husky":"^3.0.8","jest":"^24.9.0","lint-staged":"^9.4.1","p-defer":"^3.0.0","prettier":"^1.18.2","react":"^16.10.2","react-dom":"^16.10.2","react-proxy":"^3.0.0-alpha.1","react-stand-in":"^4.0.0-beta.14","react-test-renderer":"^16.10.2","rimraf":"^3.0.0"},"gitHead":"2e38683893cbbcf09da1b926dcc055e35640578b","_id":"@arthurdandrea/found@0.4.9","_nodeVersion":"12.11.1","_npmVersion":"6.11.3","dist":{"integrity":"sha512-le/AWIS6yPX9uF2V/ZgME5YG/xun2mDVld69wxs8DHAAtzja0xnxlG9Y66cILyktjbtt3RBksdeT2psx3sVi3Q==","shasum":"1d2171e12209c60ade120ecfd8655dea9d08a32b","tarball":"https://registry.npmjs.org/@arthurdandrea/found/-/found-0.4.9.tgz","fileCount":100,"unpackedSize":196897,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdn5BDCRA9TVsSAnZWagAAq9wP/0VmYbOQAkXHkhnvewyM\nLz5/Fd2zgt/2pDv+tlsOdB5eHorXCarQ9ot7xFw/VVrH0DwHW7F2Ymn8JgS4\neqxogsUmj2//DHr8s6PdZ3K6nxBoEZmdYOh6zcp84e6PRs86uCH7y9NznmRB\nQs/zVKW+i6T7BL7oZsipSPp6vasE8jH6dGBRVg1GiZhCZ9M8QeCJMNu5LO5F\n+hs3IKrAXXxXUCP7c52PpnVzLWKNutIpPYlUuhIogvlhPiiN6lxbpmI7TNWI\ncuaqXKh2pJDLxSpaCCVuwGtz3hXOMeRuk7CYhwBoRP0BxoJ0Mskge7UCloro\nJH6WKGpLTZnbzcqhiZp2jSqhzINPl83VzPNv3uqMOwh59Ut0HY5nbBCcxtlJ\nnS/tlUzH1Bw09MLfQiw2+Aizijt5gfyHJYmCViFG0UywapyEnunm21adKu1w\nns3BNxSEpb7wKYqtiH4yEet9gdveEIBgg40P5kwsyw+oIhCeruYORqewYets\n1ChlxdWYfJ0kQvxuhMOOrR5gwymfS3P4JR4QnHUqH6wBA+axpJKU3rF1PbWA\ni3NwegpITl28j8TpvXxomqjTTAjywYPB6ZxhkA23Sgz+7h6SCBJRt1Qi7qJP\npQsuUgYpBUJ3/P9uA5Whmk3i4DcwaA8m5nv6xoNXLDK/7tsVmtK9zmGGpXq5\nUYxM\r\n=o519\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA9vImD7jsjOWm63Ueib0wykdga7hRXmp2d6CaV2eu8fAiA7xUcByVKy5UCfGA3HFnfn5UcVwi0UDAwCh5N65L2SXQ=="}]},"maintainers":[{"name":"arthurdandrea","email":"aalemmar@gmail.com"}],"_npmUser":{"name":"arthurdandrea","email":"aalemmar@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/found_0.4.9_1570738242734_0.7849167703600182"},"_hasShrinkwrap":false},"0.5.3":{"name":"@arthurdandrea/found","version":"0.5.3","description":"Extensible route-based routing for React applications","main":"lib/cjs/index.js","module":"lib/esm/index.js","types":"lib/index.d.ts","scripts":{"build":"rimraf lib && npm run build:cjs && npm run build:esm && npm run build:pick && npm run build:types","build:cjs":"babel -d lib/cjs src","build:esm":"babel --env-name esm -d lib/esm src","build:pick":"cherry-pick --cjs-dir cjs --esm-dir esm --cwd lib ../src","build:types":"cpy types/*.d.ts lib","format":"eslint --fix . && npm run prettier -- --write","lint":"eslint . && npm run prettier -- -l","prepublish":"npm run build","prettier":"prettier --ignore-path .eslintignore '**/*.{md,ts,tsx}'","release":"rollout","tdd":"jest --watch","test":"npm run lint && npm run test:ts && npm run testonly -- --coverage","test:ts":"dtslint types","testonly":"jest --runInBand --verbose"},"husky":{"hooks":{"pre-commit":"lint-staged"}},"lint-staged":{"*.js":"eslint --fix","*.{md,ts,tsx}":"prettier --write","./README.md":"doctoc"},"prettier":{"printWidth":79,"singleQuote":true,"trailingComma":"all"},"jest":{"collectCoverageFrom":["src/**"],"resetMocks":true,"restoreMocks":true,"setupFiles":["<rootDir>/test/setup.js"],"testPathIgnorePatterns":["/node_modules/","<rootDir>/types/"]},"publishConfig":{"directory":"lib"},"repository":{"type":"git","url":"git+https://github.com/4Catalyzer/found.git"},"keywords":["react","router","routes","routing"],"author":{"name":"4Catalyzer"},"license":"MIT","bugs":{"url":"https://github.com/4Catalyzer/found/issues"},"homepage":"https://github.com/4Catalyzer/found#readme","dependencies":{"@babel/runtime-corejs3":"^7.6.2","@restart/context":"^2.1.4","@types/react":"^16.9.31","farce":"^0.4.1","invariant":"^2.2.4","is-promise":"^4.0.0","lodash":"^4.17.15","path-to-regexp":"^1.7.0","prop-types":"^15.7.2","react-redux":"^7.0.0","react-static-container":"^1.0.2","redux":"^4.0.4","warning":"^4.0.3"},"peerDependencies":{"react":">=16.8.0"},"devDependencies":{"@4c/babel-preset":"^7.3.5","@4c/rollout":"^2.1.9","@babel/cli":"^7.8.4","@babel/core":"^7.9.6","@types/react-dom":"^16.9.8","babel-jest":"^26.0.1","babel-plugin-add-module-exports":"^1.0.2","cherry-pick":"^0.5.0","codecov":"^3.7.0","cpy-cli":"^3.1.1","delay":"^4.3.0","doctoc":"^1.4.0","dtslint":"^3.6.4","enzyme":"^3.11.0","enzyme-adapter-react-16":"^1.15.2","eslint":"^7.1.0","eslint-config-4catalyzer-jest":"^2.0.7","eslint-config-4catalyzer-react":"^1.0.7","eslint-config-prettier":"^6.11.0","eslint-plugin-import":"^2.20.2","eslint-plugin-jest":"^23.13.1","eslint-plugin-jsx-a11y":"^6.2.3","eslint-plugin-prettier":"^3.1.3","eslint-plugin-react":"^7.20.0","eslint-plugin-react-hooks":"^4.0.2","husky":"^4.2.5","jest":"^26.0.1","lint-staged":"^10.2.6","p-defer":"^3.0.0","prettier":"^2.0.5","react":"^16.13.1","react-dom":"^16.13.1","react-proxy":"^3.0.0-alpha.1","react-stand-in":"^4.0.0-beta.21","react-test-renderer":"^16.13.1","rimraf":"^3.0.2"},"licenseText":"MIT License\n\nCopyright (c) 2016 4Catalyzer\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@arthurdandrea/found@0.5.3","dist":{"shasum":"7fcf2e3e2afbf6a86c38378a71bf6207a8fbfbf4","integrity":"sha512-HWZALGHcthj1ofacA/do/FqOv0ahUwqF8ZRvUBohH7ojRPhlJncKdL5NXWuyhyFLorbSYfXRtfT0Eti3fkOE4Q==","tarball":"https://registry.npmjs.org/@arthurdandrea/found/-/found-0.5.3.tgz","fileCount":199,"unpackedSize":280756,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1BphCRA9TVsSAnZWagAAEWoP/iOa6OZoHNlQ66JrRZME\nFXLRjgqiEDH21OZu7Nfgw0A+d8elDamFGMalN0KQZ31ZmZrA9K9JQbuCT88x\nlURL3K+4MF4EBhBdRxvk9y7eSJV4pXy8SOUOkd+crqcs6y31wQx9pXXMsSKR\nUNRmLclK0djpo8sMP7wZC7zKmqmh5SyZo+lZh5++TQxYiXSF0aPFu0MIJvlk\nXwUqGTQqbA8yr+SHH+QnSNyIWgLDu8myFmzePjr4p9jcBQssDWUY2ihncrP/\ni+bcyEydJYvplbo5xGj6Vjhme9069aPXQBPrwjlHNwzBLv4DaR6DExjO0Y7v\nj6TaOP+jvuPnFxcVzqNYF13LzL+mSwf1x+hZmQzDllmYtIeChp6ddqdlyN98\n1p/CIVRJwc2w+OLZM2wwCPCQtKDlubi/ij8CddJVE7AZFP+fopZOZvKGo3+5\nIyDoNS54oHY1CMBgfyzRsiyZoJoqErwV7GkjMIMMxaw6gxOvgcVIG7ert7w7\nlaKTMtzxJ2wJjPcdlhImmDYBqoK29qCOLheKF4Aw3VijlDh6+n2R+XQh0YT2\n3TPlKmg6bAaSDhweu9EslF0O9ontcP/wZYv5n/TtDf0/M4sL5aF1hPrAhqsJ\n9ATIgGZACHLs6dBBYaIbhyNUgsNtAays4Ojtrq8XiFWx5/XVuEd4lnXUtHrk\nY2aq\r\n=4RlT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEbYSxBR+/6CUBsJ0uftECNY5FyclxJqAUT/KA9M9E2iAiEAi5MWjf/BwvP46uaTrD+LG3/clNrdBLVXOW3vi+jpKzY="}]},"maintainers":[{"name":"arthurdandrea","email":"aalemmar@gmail.com"}],"_npmUser":{"name":"arthurdandrea","email":"aalemmar@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/found_0.5.3_1590958688999_0.5765529322187504"},"_hasShrinkwrap":false}},"time":{"created":"2019-10-10T20:10:42.525Z","0.4.9":"2019-10-10T20:10:43.092Z","modified":"2022-04-04T15:37:33.619Z","0.5.3":"2020-05-31T20:58:09.128Z"},"maintainers":[{"name":"arthurdandrea","email":"aalemmar@gmail.com"}],"description":"Extensible route-based routing for React applications","homepage":"https://github.com/4Catalyzer/found#readme","keywords":["react","router","routes","routing"],"repository":{"type":"git","url":"git+https://github.com/4Catalyzer/found.git"},"author":{"name":"4Catalyzer"},"bugs":{"url":"https://github.com/4Catalyzer/found/issues"},"license":"MIT","readme":"# Found [![Travis][build-badge]][build] [![npm][npm-badge]][npm]\n\n_Extensible route-based routing for React applications._\n\nFound is a router for [React](https://reactjs.org/) applications with a focus on power and extensibility. Found uses static route configurations. This enables efficient code splitting and data fetching with nested routes. Found also offers extensive control over indicating those loading states, even for routes with code bundles that have not yet been downloaded.\n\nFound is designed to be extremely customizable. Most pieces of Found such as the path matching algorithm and the route element resolution can be fully replaced. This allows [extensions](#extensions) such as [Found Relay](https://github.com/4Catalyzer/found-relay) to provide first-class support for different use cases.\n\nFound uses [Redux](https://redux.js.org/) for state management and [Farce](https://github.com/4Catalyzer/farce) for controlling browser navigation. It can integrate with your existing store and connected components.\n\n<!-- prettier-ignore-start -->\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [Usage](#usage)\n- [Examples](#examples)\n- [Extensions](#extensions)\n- [Guide](#guide)\n  - [Installation](#installation)\n  - [Basic usage](#basic-usage)\n  - [Route configuration](#route-configuration)\n    - [`path`](#path)\n    - [`Component` or `getComponent`](#component-or-getcomponent)\n    - [`data` or `getData`](#data-or-getdata)\n    - [`defer`](#defer)\n    - [`render`](#render)\n    - [Named child routes](#named-child-routes)\n    - [Redirects](#redirects)\n    - [Error handling](#error-handling)\n    - [Custom route classes](#custom-route-classes)\n  - [Router configuration](#router-configuration)\n    - [`createBrowserRouter`](#createbrowserrouter)\n    - [`createFarceRouter`](#createfarcerouter)\n    - [`createConnectedRouter`](#createconnectedrouter)\n  - [Navigation](#navigation)\n    - [Links](#links)\n    - [Programmatic navigation](#programmatic-navigation)\n    - [Blocking navigation](#blocking-navigation)\n  - [Redux integration](#redux-integration)\n  - [Hot reloading](#hot-reloading)\n  - [Server-side rendering](#server-side-rendering)\n    - [Server-side rendering with custom Redux store](#server-side-rendering-with-custom-redux-store)\n  - [Minimizing bundle size](#minimizing-bundle-size)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n<!-- prettier-ignore-end -->\n\n## Usage\n\n```js\nimport {\n  createBrowserRouter,\n  HttpError,\n  makeRouteConfig,\n  Redirect,\n  Route,\n} from 'found';\n\n/* ... */\n\nconst BrowserRouter = createBrowserRouter({\n  routeConfig: makeRouteConfig(\n    <Route path=\"/\" Component={AppPage}>\n      <Route Component={MainPage} />\n      <Route path=\"widgets\">\n        <Route Component={WidgetsPage} getData={fetchWidgets} />\n        <Route\n          path=\"widgets/:widgetId\"\n          getComponent={() =>\n            System.import('./WidgetPage').then((module) => module.default)\n          }\n          getData={({ params: { widgetId } }) =>\n            fetchWidget(widgetId).catch(() => {\n              throw new HttpError(404);\n            })\n          }\n          render={({ Component, props }) =>\n            Component && props ? (\n              <Component {...props} />\n            ) : (\n              <div>\n                <small>Loading</small>\n              </div>\n            )\n          }\n        />\n      </Route>\n      <Redirect from=\"widget/:widgetId\" to=\"/widgets/:widgetId\" />\n    </Route>,\n  ),\n\n  renderError: ({ error }) => (\n    <div>{error.status === 404 ? 'Not found' : 'Error'}</div>\n  ),\n});\n\nReactDOM.render(<BrowserRouter />, document.getElementById('root'));\n```\n\nThis configuration will set up the following routes:\n\n- `/`\n  - This renders `<AppPage><MainPage /></AppPage>`\n- `/widget`\n  - This renders `<AppPage><WidgetsPage /><AppPage>`\n  - This will load the data for `<WidgetsPage>` when the user navigates to this route\n  - This will continue to render the previous routes while the data for `<WidgetsPage>` are loading\n- `/widgets/${widgetId}` (e.g. `/widgets/foo`)\n  - This renders `<AppPage><WidgetPage /></AppPage>`\n  - This will load the code and data for `<WidgetPage>` when the user navigates to this route\n  - This will render the text \"Loading\" in place of `<WidgetPage>` while the code and data for `<WidgetPage>` are loading\n- `/widget/${widgetId}` (e.g. `/widget/foo`)\n  - This redirects to `/widgets/${widgetId}`, then renders as above\n\n```js\n// AppPage.js\n\nimport { Link } from 'found';\nimport React from 'react';\n\nfunction AppPage({ children }) {\n  return (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\" activeClassName=\"active\" exact>\n            Main\n          </Link>\n        </li>\n        <li>\n          <Link to=\"/widgets/foo\" activeClassName=\"active\">\n            Foo widget\n          </Link>\n        </li>\n      </ul>\n\n      {children}\n    </div>\n  );\n}\n\nexport default AppPage;\n```\n\n## Examples\n\n- [Basic usage](/examples/basic)\n- [Basic usage with JSX route configuration](/examples/basic-jsx)\n- [Global pending state](/examples/global-pending)\n- [Navigation listener usage](/examples/navigation-listener)\n- [Shared Redux store](/examples/redux)\n- [Hot reloading](/examples/hot-reloading)\n- [Server-side rendering](/examples/universal)\n- [Server-side rendering with shared Redux store](/examples/universal-redux)\n\n## Extensions\n\n- [Found Scroll](https://github.com/4Catalyzer/found-scroll): browser scroll management\n- [Found Named Routes](https://github.com/4Catalyzer/found-named-routes): named route support\n- [Found Relay](https://github.com/4Catalyzer/found-relay): [Relay](https://relay.dev/) integration\n\n## Guide\n\n### Installation\n\n```\n$ npm i -S react\n$ npm i -S found\n```\n\n### Basic usage\n\nDefine a route configuration as an array of objects, or as JSX with `<Route>` elements using `makeRouteConfig`.\n\n```js\nconst routeConfig = [\n  {\n    path: '/',\n    Component: AppPage,\n    children: [\n      {\n        Component: MainPage,\n      },\n      {\n        path: 'foo',\n        Component: FooPage,\n        children: [\n          {\n            path: 'bar',\n            Component: BarPage,\n          },\n        ],\n      },\n    ],\n  },\n];\n\n// This is equivalent:\nconst jsxRouteConfig = makeRouteConfig(\n  <Route path=\"/\" Component={AppPage}>\n    <Route Component={MainPage} />\n    <Route path=\"foo\" Component={FooPage}>\n      <Route path=\"bar\" Component={BarPage} />\n    </Route>\n  </Route>,\n);\n```\n\nCreate a router using your route configuration. For a basic router that uses the HTML5 History API, use `createBrowserRouter`.\n\n```js\nconst BrowserRouter = createBrowserRouter({ routeConfig });\n```\n\nRender this router component into the page.\n\n```js\nReactDOM.render(<BrowserRouter />, document.getElementById('root'));\n```\n\nIn components rendered by the router, use `<Link>` to render links that navigate when clicked and display active state.\n\n```js\n<Link to=\"/foo\" activeClassName=\"active\">\n  Foo\n</Link>\n```\n\n### Route configuration\n\nA route object under the default matching algorithm and route element resolver consists of 4 properties, all of which are optional:\n\n- `path`: a string defining the pattern for the route\n- `Component` or `getComponent`: the component for the route, or a method that returns the component for the route\n- `data` or `getData`: additional data for the route, or a method that returns additional data for the route\n- `defer`: whether to wait for all parent `data` or `getData` promises to resolve before getting data for this route and its descendants\n- `render`: a method that returns the element for the route\n- `children`: an array of child route objects, or an object of those arrays; if using JSX configuration components, this comes from the JSX children\n\nA route configuration consists of an array of route objects. You can generate such an array of route objects from JSX with `<Route>` elements using `makeRouteConfig`.\n\n#### `path`\n\nSpecify a `path` pattern to control the paths for which a route is active. These patterns are handled using [Path-to-RegExp](https://github.com/pillarjs/path-to-regexp) and follow the rules there. Both named and unnamed parameters will be captured in `params` and `routeParams` as below. The following are common patterns:\n\n- `/path/subpath`\n  - Matches `/path/subpath`\n- `/path/:param`\n  - Matches `/path/foo` with `params` of `{ param: 'foo' }`\n- `/path/:regexParam(\\\\d+)`\n  - Matches `/path/123` with `params` of `{ regexParam: '123' }`\n  - Does not match `/path/foo`\n- `/path/:optionalParam?`\n  - Matches `/path/foo` with `params` of `{ optionalParam: 'foo' }`\n  - Matches `/path` with `params` of `{ optionalParam: undefined }`\n- `/path/*`\n  - Matches `/path/foo/bar`\n\nRoutes are matched based on their `path` properties in a depth-first manner, where `path` on the route must match the prefix of the remaining current path. Routing continues through any routes that do not have `path` set. To configure a default or \"index\" route, use a route with no `path`.\n\n#### `Component` or `getComponent`\n\nDefine the component for a route using either a `Component` field or a `getComponent` method. `Component` should be a component class or function. `getComponent` should be a function that returns a component class or function, or a promise that resolves to either of those. Routes that specify neither will still match if applicable, but will not have a component associated with them.\n\nGiven the following route configuration:\n\n```js\nconst routes = makeRouteConfig(\n  <Route path=\"/\" Component={AppPage}>\n    <Route Component={MainPage}>\n      <Route Component={MainSection} />\n      <Route path=\"other\" Component={OtherSection} />\n    </Route>\n    <Route path=\"widgets\">\n      <Route Component={WidgetsPage} />\n      <Route path=\":widgetId\" Component={WidgetPage} />\n    </Route>\n  </Route>,\n);\n```\n\nThe router will have routes as follows:\n\n- `/`, rendering:\n\n```js\n<AppPage>\n  <MainPage>\n    <MainSection />\n  </MainPage>\n</AppPage>\n```\n\n- `/other`, rendering:\n\n```js\n<AppPage>\n  <MainPage>\n    <OtherSection />\n  </MainPage>\n</AppPage>\n```\n\n- `/widgets`, rendering:\n\n```js\n<AppPage>\n  <WidgetsPage />\n</AppPage>\n```\n\n- `/widgets/${widgetId}` (e.g. `/widgets/foo`), rendering:\n\n```js\n<AppPage>\n  <WidgetPage />\n</AppPage>\n```\n\nBy default, route components receive the following additional props describing the current routing state:\n\n- `match`: an object with router state properties, conforming to the `matchShape` prop type validator\n  - `location`: the current [location object](https://github.com/4Catalyzer/farce#locations-and-location-descriptors)\n  - `params`: the union of path parameters for all matched routes\n  - `routes`: an array of all matched route objects\n  - `route`: the route object corresponding to this component\n  - `routeParams`: the path parameters for `route`\n- `router`: an object with static router properties, conforming to the `routerShape` prop type validator\n  - `push(location)`: navigates to a new location\n  - `replace(location)`: replaces the existing history entry\n  - `go(delta)`: moves `delta` steps in the history stack\n  - `isActive(match, location, { exact })`: for `match` as above, returns whether `match` corresponds to `location` or a subpath of `location`; if `exact` is set, returns whether `match` corresponds exactly to `location`\n  - `matcher`: an object implementing the matching algorithm\n    - `format(pattern, params)`: returns the path string for a pattern of the same format as a route `path` and a object of the corresponding path parameters\n  - `addNavigationListener(listener)`: adds a [navigation listener](https://github.com/4Catalyzer/farce#navigation-listeners) that can [block navigation](#blocking-navigation)\n\nThe `getComponent` method receives an object containing the same properties as the `match` object above, with an additional `router` property as above.\n\n#### `data` or `getData`\n\nSpecify the `data` property or `getData` method to inject data into a route component as the `data` prop. `data` can be any value. `getData` can be any value, or a promise that resolves to any value. `getData` receives an object containing the routing state, as described above for `getComponent`.\n\nThe `getData` method is intended for loading additional data from your back end for a given route. By design, all requests for asynchronous component and data dependencies will be issued in parallel. Found uses static route configurations specifically to enable issuing these requests in parallel.\n\nIf you need additional context such as a store instance to fetch data, specify this as the `matchContext` prop to your router. This context value will then be available as the `context` property on the argument to `getData`.\n\n```js\nconst route = {\n  path: 'widgets/:widgetId',\n  Component: WidgetPage,\n  getData: ({ params, context }) =>\n    context.store.dispatch(Actions.getWidget(params.widgetId)),\n};\n\n// <Router matchContext={{ store }} />\n```\n\nIt does not make sense to specify `data` or `getData` if the route does not have a component as above or a `render` method as below.\n\n#### `defer`\n\nBy default, Found will issue all data fetching operations in parallel. However, if you wish to defer data fetching for a given route until its parent data promises has been resolved, you may do so by setting `defer` on the route.\n\n```js\n<Route Component={Parent} getData={getParentData}>\n  <Route Component={Child} getData={getChildData} defer />\n</Route>\n```\n\nSetting `defer` on a route will make the resolver defer calling its `getData` method and the `getData` methods on all of its descendants until all of its parent data promises have resolved.\n\nThis should be a relatively rare scenario, as generally user experience is better if all data are fetched in parallel, but in some cases it can be desirable to avoid making data fetching operations that are guaranteed to fail, such as when the user is not authenticated, when optimizing for client bandwidth usage or API utilization.\n\n#### `render`\n\nSpecify the `render` method to further customize how the route renders. It receives an object with the following properties:\n\n- `match`: the routing state object, as above\n- `Component`: the component for the route, if any; `null` if the component has not yet been loaded\n- `props`: the default props for the route component, specifically `match` with `data` as an additional property; `null` if `data` have not yet been loaded\n- `data`: the data for the route, as above; `null` if the data have not yet been loaded\n\nIt should return:\n\n- another function that receives its children as an argument and returns a React element; this function receives\n  - a React element when not using named child routes\n  - an object when using named child routes\n  - `null` when it has no children\n- a React element to render that element\n- `undefined` if it has a pending asynchronous component or data dependency and is not ready to render\n- `null` to render its children (or nothing of there are no children)\n\nNote that, when specifying this `render` method, `Component` or `getComponent` will have no effect other than controlling the value of the `Component` property on the argument to `render`. Additionally, the behavior is different between returning a function that returns `null` and returning `null` directly; in the former case, nothing will be rendered, while in the latter case, the route's children will be rendered.\n\nYou can use this method to render per-route loading state.\n\n```js\nfunction render({ Component, props }) {\n  if (!Component || !props) {\n    return <LoadingIndicator />;\n  }\n\n  return <Component {...props} />;\n}\n```\n\nIf any matched routes have unresolved asynchronous component or data dependencies, the router will initially attempt to render all such routes in their loading state. If those routes all implement `render` methods and return non-`undefined` values from their `render` methods, the router will render the matched routes in their loading states. Otherwise, the router will continue to render the previous set of routes until all asynchronous dependencies resolve.\n\n#### Named child routes\n\nSpecify an object for the `children` property on a route to set up named child routes. A route with named child routes will match only if every route group matches. The elements corresponding to the child routes will be available on their parent as props with the same name as the route groups.\n\n```js\nfunction AppPage({ nav, main }) {\n  return (\n    <div className=\"app\">\n      <div className=\"nav\">{nav}</div>\n      <div className=\"main\">{main}</div>\n    </div>\n  );\n}\n\nconst route = {\n  path: '/',\n  Component: AppPage,\n  children: [\n    {\n      path: 'foo',\n      children: {\n        nav: [\n          {\n            path: '(.*)?',\n            Component: FooNav,\n          },\n        ],\n        main: [\n          {\n            path: 'a',\n            Component: FooA,\n          },\n          {\n            path: 'b',\n            Component: FooB,\n          },\n        ],\n      },\n    },\n    {\n      path: 'bar',\n      children: {\n        nav: [\n          {\n            path: '(.*)?',\n            Component: BarNav,\n          },\n        ],\n        main: [\n          {\n            Component: BarMain,\n          },\n        ],\n      },\n    },\n  ],\n};\n\nconst jsxRoute = (\n  <Route path=\"/\" Component={AppPage}>\n    <Route path=\"foo\">\n      {{\n        nav: <Route path=\"(.*)?\" Component={FooNav} />,\n        main: [\n          <Route path=\"a\" Component={FooA} />,\n          <Route path=\"b\" Component={FooB} />,\n        ],\n      }}\n    </Route>\n    <Route path=\"bar\">\n      {{\n        nav: <Route path=\"(.*)?\" Component={BarNav} />,\n        main: <Route Component={BarMain} />,\n      }}\n    </Route>\n  </Route>\n);\n```\n\n#### Redirects\n\nThe `Redirect` route class sets up static redirect routes. You can also use it to create JSX `<Redirect>` elements for use with `makeRouteConfig`. This class takes `from` and `to` properties. `from` should be a path pattern as for normal routes above. `to` can be either a path pattern or a function. If it is a path pattern, the router will populate path parameters appropriately. If it is a function, it will receive the same routing state object as `getComponent` and `getData`, as described above.\n\n```js\nconst redirect1 = new Redirect({\n  from: 'widget/:widgetId',\n  to: '/widgets/:widgetId',\n});\n\nconst redirect2 = new Redirect({\n  from: 'widget/:widgetId',\n  to: ({ params }) => `/widgets/${params.widgetId}`,\n});\n\nconst jsxRedirect1 = (\n  <Redirect from=\"widget/:widgetId\" to=\"/widgets/:widgetId\" />\n);\n\nconst jsxRedirect2 = (\n  <Redirect\n    from=\"widget/:widgetId\"\n    to={({ params }) => `/widgets/${params.widgetId}`}\n  />\n);\n```\n\nIf you need more custom control over redirection, throw a `RedirectException` in your route's `render` method with a [location descriptor](https://github.com/4Catalyzer/farce#locations-and-location-descriptors) for the redirect destination.\n\n```js\nconst customRedirect = {\n  getData: fetchRedirectInfo,\n  render: ({ data }) => {\n    if (data) {\n      throw new RedirectException(data.redirectLocation);\n    }\n  },\n};\n```\n\n#### Error handling\n\nThe `HttpError` class signals handled router-level error states. This error class takes a status value that should be an integer corresponding to an HTTP error code and an optional data value of any type. You can handle these errors and render appropriate error feedback in the router-level render method described below.\n\n```js\nthrow new HttpError(status, data);\n```\n\nThe router will throw a `new HttpError(404)` in the case when no routes match the current location. Otherwise, you can throw `HttpError` instances in the `getComponent`, `getData`, and `render` methods to signal error states.\n\n```js\nconst route = {\n  path: 'widgets/:widgetId',\n  Component: WidgetPage,\n  getData: ({ params: { widgetId } }) =>\n    fetchWidget(widgetId).catch(() => {\n      throw new HttpError(404);\n    }),\n};\n```\n\n#### Custom route classes\n\nYou can implement reusable logic in routes with a custom route class. When extending `Route`, methods defined on the class will be overridden by explicitly specified route properties. You can use custom route classes for either object route configurations or JSX route configurations.\n\n> **Note:** To avoid issues with [React Hot Loader](https://gaearon.github.io/react-hot-loader/), custom route classes should usually extend `Route`.\n\n```js\nclass AsyncRoute extends Route {\n  // An explicit render property on the route will override this.\n  render({ Component, props }) {\n    return Component && props ? (\n      <Component {...props} />\n    ) : (\n      <LoadingIndicator />\n    );\n}\n\nconst myRoute = new AsyncRoute(properties);\nconst myJsxRoute = <AsyncRoute {...properties} />;\n```\n\n### Router configuration\n\nFound exposes a number of router component class factories at varying levels of abstraction. These factories accept the static configuration properties for the router, such as the route configuration. The use of static configuration allows for efficient, parallel data fetching and state management as above.\n\n#### `createBrowserRouter`\n\n`createBrowserRouter` creates a basic router component class that uses the HTML5 History API for navigation. This factory uses reasonable defaults that should fit a variety use cases.\n\n```js\nimport { createBrowserRouter } from 'found';\n\n/* ... */\n\nconst BrowserRouter = createBrowserRouter({\n  routeConfig,\n\n  renderError: ({ error }) => (\n    <div>{error.status === 404 ? 'Not found' : 'Error'}</div>\n  ),\n});\n\nReactDOM.render(<BrowserRouter />, document.getElementById('root'));\n```\n\n`createBrowserRouter` takes an options object. The only mandatory property on this object is `routeConfig`, which should be a route configuration as above.\n\nThe options object also accepts a number of optional properties:\n\n- `historyMiddlewares`: an array of Farce history middlewares; by default, an array containing only `queryMiddleware`\n- `historyOptions`: additional configuration options for the Farce history store enhancer\n- `renderPending`: a custom render function called when some routes are not yet ready to render, due to those routes have unresolved asynchronous dependencies and no route-level `render` method for handling the loading state\n- `renderReady`: a custom render function called when all routes are ready to render\n- `renderError`: a custom render function called if an `HttpError` is thrown while resolving route elements\n- `render`: a custom render function called in all cases, superseding `renderPending`, `renderReady`, and `renderError`; by default, this is `createRender({ renderPending, renderReady, renderError })`\n\nThe `renderPending`, `renderReady`, `renderError`, and `render` functions receive the routing state object as an argument, with the following additional properties:\n\n- `elements`: if present, an array the resolved elements for the matched routes; the array item will be `null` for routes without elements\n- `error`: if present, the `HttpError` object thrown during element resolution with properties describing the error\n  - `status`: the status code; this is the first argument to the `HttpError` constructor\n  - `data`: additional error data; this is the second argument to the `HttpError` constructor\n\nYou should specify a `renderError` function or otherwise handle error states. You can specify `renderPending` and `renderReady` functions to indicate loading state globally; the [global pending state example](/examples/global-pending) demonstrates doing this using a static container.\n\nThe created `<BrowserRouter>` accepts an optional `matchContext` prop as described above that injects additional context into the route resolution methods.\n\n#### `createFarceRouter`\n\n`createFarceRouter` exposes additional configuration for customizing navigation management and route element resolution. To enable minimizing bundle size, it omits some defaults from `createBrowserRouter`.\n\n```js\nimport { BrowserProtocol, queryMiddleware } from 'farce';\nimport { createFarceRouter, resolver } from 'found';\n\n/* ... */\n\nconst FarceRouter = createFarceRouter({\n  historyProtocol: new BrowserProtocol(),\n  historyMiddlewares: [queryMiddleware],\n  routeConfig,\n\n  renderError: ({ error }) => (\n    <div>{error.status === 404 ? 'Not found' : 'Error'}</div>\n  ),\n});\n\nReactDOM.render(\n  <FarceRouter resolver={resolver} />,\n  document.getElementById('root'),\n);\n```\n\nThe options object for `createFarceRouter` should have a `historyProtocol` property that has a history protocol object. For example, to use the HTML History API as with `createBrowserRouter`, you would provide `new BrowserProtocol()`.\n\nThe created `<FarceRouter>` manages setting up and providing a Redux store with the appropriate configuration internally. It also requires a `resolver` prop with the route element resolver object. For routes configured as above, this should be the `resolver` object in this library.\n\n#### `createConnectedRouter`\n\n`createConnectedRouter` creates a router that works with an existing Redux store and provider.\n\n```js\nimport {\n  Actions as FarceActions,\n  BrowserProtocol,\n  createHistoryEnhancer,\n  queryMiddleware,\n} from 'farce';\nimport {\n  createConnectedRouter,\n  createMatchEnhancer,\n  createRender,\n  foundReducer,\n  Matcher,\n  resolver,\n} from 'found';\nimport { Provider } from 'react-redux';\nimport { combineReducers, compose, createStore } from 'redux';\n\n/* ... */\n\nconst store = createStore(\n  combineReducers({\n    found: foundReducer,\n  }),\n  compose(\n    createHistoryEnhancer({\n      protocol: new BrowserProtocol(),\n      middlewares: [queryMiddleware],\n    }),\n    createMatchEnhancer(new Matcher(routeConfig)),\n  ),\n);\n\nstore.dispatch(FarceActions.init());\n\nconst ConnectedRouter = createConnectedRouter({\n  render: createRender({\n    renderError: ({ error }) => (\n      <div>{error.status === 404 ? 'Not found' : 'Error'}</div>\n    ),\n  }),\n});\n\nReactDOM.render(\n  <Provider store={store}>\n    <ConnectedRouter resolver={resolver} />\n  </Provider>,\n  document.getElementById('root'),\n);\n```\n\n> **Note:** Found uses `redux` and `react-redux` as direct dependencies for the convenience of users not directly using Redux. If you are directly using Redux, either ensure that you have the same versions of `redux` and `react-redux` installed as used in Found, or use package manager or bundler resolutions to force Found to use the same versions of those packages that you are using directly. Found is compatible with any current release of `redux` or `react-redux`.\n\nWhen creating a store for use with the created `<ConnectedRouter>`, you should install the `foundReducer` reducer under the `found` key. You should also use a store enhancer created with `createHistoryEnhancer` from Farce and a store enhancer created with `createMatchEnhancer`, which must go after the history store enhancer. Dispatch `FarceActions.init()` after setting up your store to initialize the event listeners and the initial location for the history store enhancer.\n\n`createConnectedRouter` ignores the `historyProtocol`, `historyMiddlewares`, and `historyOptions` properties on its options object.\n\n`createConnectedRouter` also accepts an optional `getFound` property. If you installed `foundReducer` on a key other than `found`, specify the `getFound` function to retrieve the reducer state.\n\n### Navigation\n\nFound provides a high-level abstractions such as a link component for controlling browser navigation. Under the hood, it delegates to [Farce](https://github.com/4Catalyzer/farce) for implementation, and as such can also be controlled directly via the Redux store.\n\n#### Links\n\nThe `<Link>` component renders a link with optional active state indication.\n\n```js\nconst link1 = (\n  <Link to=\"/widgets/foo\" activeClassName=\"active\">\n    Foo widget\n  </Link>\n);\n\nconst link2 = (\n  <Link\n    as={CustomAnchor}\n    to={{\n      pathname: '/widgets/bar',\n      query: { the: query },\n    }}\n    activePropName=\"active\"\n  >\n    Bar widget with query\n  </Link>\n);\n\nconst link3 = (\n  <Link\n    to={{\n      pathname: '/widgets/bar',\n      query: { the: query },\n    }}\n  >\n    {({ href, active, onClick }) => (\n      <CustomButton href={href} active={active} onClick={onClick} />\n    )}\n  </Link>\n);\n```\n\n`<Link>` accepts the following props:\n\n- `to`: a [location descriptor](https://github.com/4Catalyzer/farce#locations-and-location-descriptors) for the link's destination\n- `exact`: if specified, the link will only render as active if the current location exactly matches the `to` location descriptor; by default, the link also will render as active on subpaths of the `to` location descriptor\n- `activeClassName`: if specified, a CSS class to append to the component's CSS classes when the link is active\n- `activeStyle`: if specified, a style object to append merge with the component's style object when the link is active\n- `activePropName`: if specified, a prop to inject with a boolean value with the link's active state\n- `as`: if specified, the custom element type to use for the link; by default, the link will render an `<a>` element\n\nA link will navigate per its `to` location descriptor when clicked. You can prevent this navigation by providing an `onClick` handler that calls `event.preventDefault()`.\n\n`<Link>` accepts a function for `children`. If `children` is a function, then `<Link>` will render the return value of that function, and will ignore `activeClassName`, `activeStyle`, `activePropName`, and `as` above. The function will be called with an object with the following properties:\n\n- `href`: the URL for the link\n- `active`: whether the link is active\n- `onClick`: the click event handler for the link element\n\nOtherwise, `<Link>` forwards additional props to the child element.\n\n#### Programmatic navigation\n\nThe `withRouter` HOC wraps an existing component class or function and injects `match` and `router` props, as on route components above. You can use this HOC to create components that navigate programmatically in event handlers.\n\n```js\nconst propTypes = {\n  match: matchShape.isRequired,\n  router: routerShape.isRequired,\n};\n\nclass MyButton extends React.Component {\n  onClick = () => {\n    this.props.router.replace('/widgets');\n  };\n\n  render() {\n    return (\n      <button onClick={this.onClick}>\n        Current widget: {this.props.match.params.widgetId}\n      </button>\n    );\n  }\n}\n\nMyButton.propTypes = propTypes;\n\nexport default withRouter(MyButton);\n```\n\nThe `useRouter` Hook provides the same capabilities.\n\n```js\nfunction MyButton() {\n  const { match, router } = useRouter();\n\n  const onClick = useCallback(() => {\n    router.replace('/widgets');\n  }, [router]);\n\n  return (\n    <button onClick={onClick}>Current widget: {match.params.widgetId}</button>\n  );\n}\n```\n\n#### Blocking navigation\n\nThe `router.addNavigationListener` method adds a [navigation listener](https://github.com/4Catalyzer/farce#navigation-listeners) that can block navigation. This method accepts a navigation listener function and an optional options object. It returns a function that removes the navigation listener.\n\n```js\nfunction MyForm(props) {\n  const [dirty, setDirty] = useState(false);\n  const { router } = useRouter();\n\n  useEffect(\n    () =>\n      dirty\n        ? router.addNavigationListener(\n            () =>\n              'You have unsaved input. Are you sure you want to leave this page?',\n          )\n        : undefined,\n    [dirty],\n  );\n\n  /* ... */\n}\n```\n\nThe navigation listener function receives the location to which the user is attempting to navigate as its argument. Return `true` or `false` from this function to allow or block navigation respectively. Return a string to display a default confirmation dialog to the user. Return a nully value to use the next navigation listener if present, or else allow navigation. Return a promise to defer allowing or blocking navigation until the promise resolves; you can use this to display a custom confirmation dialog.\n\nIf you want to run your navigation listeners when the user attempts to leave the page, set `beforeUnload` in the options object. If this option is enabled, your navigation listeners will be called with a `null` location when the user attempts to leave the page. In this scenario, the navigation listener must return a non-promise value.\n\n```js\nrouter.addNavigationListener(\n  (location) => {\n    if (!location) {\n      return false;\n    }\n\n    return asyncConfirm(location);\n  },\n  { beforeUnload: true },\n);\n```\n\nThe [navigation listener usage example](/examples/navigation-listener) demonstrates the use of navigation listeners in more detail, including the use of the `beforeUnload` option.\n\n### Redux integration\n\nFound uses Redux to manage all serializable state. Farce uses Redux actions for navigation. As such, you can also access those serializable parts of the routing state from the store state, and you can navigate by dispatching actions.\n\nIf you are using your own Redux store, use `createConnectedRouter` as described above to have a single store that contains both routing state and other application state. Additionally, if you need to make this store available in `getData` methods on routes, pass it to `matchContext` on the router component as described above.\n\nTo access the current routing state, connect to the `resolvedMatch` property of the `foundReducer` state. To navigate, dispatch the appropriate actions from Farce.\n\n```js\nimport { Actions as FarceActions } from 'farce';\nimport { connect } from 'react-redux';\n\nconst MyConnectedComponent = connect(\n  ({ found: { resolvedMatch } }) => ({\n    location: resolvedMatch.location,\n    params: resolvedMatch.params,\n  }),\n  {\n    push: FarceActions.push,\n  },\n)(MyComponent);\n```\n\n### Hot reloading\n\nWhen using hot reloading via [React Hot Loader](https://gaearon.github.io/react-hot-loader/), mark your route configuration with `hotRouteConfig` to enable hot reloading for your route configuration as well.\n\n```js\nexport default hotRouteConfig(routeConfig);\n```\n\nThis will replace the route configuration and rerun the match with the current location whenever the route configuration changes. As with React Hot Loader, this is safe to do unconditionally, as it will have no effect in production.\n\n> **Note:** Changes to route components also count as route configuration changes. If your routes have asynchronous data dependencies, ensure that the data are cached. Otherwise, the router will refetch data every time a route component changes.\n\n`createMatchEnhancer` takes an optional `getFound` function as its second argument. If you installed `foundReducer` on a key other than `found`, specify the `getFound` function to retrieve the reducer state to enable this hot reloading support.\n\nYou can also manually replace the route configuration and rerun the match by calling `found.replaceRouteConfig` on a Found-enhanced store object.\n\n### Server-side rendering\n\nFound supports server-side rendering for universal applications. Functionality specific to server-side rendering is available in `found/server`.\n\nTo render your application on the server, use `getFarceResult`.\n\n```js\nimport { getFarceResult } from 'found/server';\n\n/* ... */\n\napp.use(async (req, res) => {\n  const { redirect, status, element } = await getFarceResult({\n    url: req.url,\n    routeConfig,\n    render,\n  });\n\n  if (redirect) {\n    res.redirect(302, redirect.url);\n    return;\n  }\n\n  res.status(status).send(`\n<!DOCTYPE html>\n<html>\n\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Found Universal Example</title>\n</head>\n\n<body>\n<div id=\"root\">${ReactDOMServer.renderToString(element)}</div>\n\n<script src=\"/static/bundle.js\"></script>\n</body>\n\n</html>\n  `);\n});\n```\n\n`getFarceResult` takes an options object. This object must include the `url` property that is the full path of the current request, along with the `routeConfig` and `render` properties needed to create a Farce router component class normally.\n\nThe options object for `getFarceResult` also takes the `historyMiddlewares` and `historyOptions` properties, as above for creating Farce router component classes. This options object also takes optional `matchContext` and `resolver` properties, as described above as props for router components. `resolver` defaults to the standard `resolver` object in this library.\n\n`getFarceResult` returns a promise for an object with the following properties:\n\n- `redirect`: if present, indicates that element resolution triggered a redirect; `redirect.url` contains the full path for the redirect location\n- `status`: if there was no redirect, the HTTP status code for the response; this will be `error.status` from any encountered `HttpError`, or 200 otherwise\n- `element`: if there was no redirect, the React element corresponding to the router component on the client\n\nThis promise resolves when all asynchronous dependencies are available. If your routes require asynchronous data, e.g. from `getData` methods, you may want to dehydrate those data on the server, then rehydrate them on the client, to avoid the client having to request those data again.\n\nWhen using server-side rendering, you need to delay the initial render on the client, such that the initial client-rendered markup matches the server-rendered markup. To do so, use `createInitialBrowserRouter` or `createInitialFarceRouter` instead of `createBrowserRouter` or `createFarceRouter` respectively.\n\n```js\nimport { createInitialBrowserRouter } from 'found';\n\n/* ... */\n\n(async () => {\n  const BrowserRouter = await createInitialBrowserRouter({\n    routeConfig,\n    render,\n  });\n\n  ReactDOM.render(<BrowserRouter />, document.getElementById('root'));\n})();\n```\n\nThese behave similarly to their counterparts above, except that the options object for `createInitialBrowserRouter` requires a `render` method, and ignores the `renderPending`, `renderReady`, and `renderError` properties. Additionally, these functions take the initial `matchContext` and `resolver` if relevant as properties on the options object, rather than as props.\n\n#### Server-side rendering with custom Redux store\n\nFound exposes lower-level functionality for doing server-side rendering for use with your own Redux store, as with `createConnectedRouter` above. On the server, use `getStoreRenderArgs` to get a promise for the arguments to your `render` function, then wrap the rendered elements with a `<RouterProvider>`.\n\n```js\nimport { getStoreRenderArgs } from 'found';\nimport { RouterProvider } from 'found/server';\n\n/* ... */\n\napp.use(async (req, res) => {\n  /* ... */\n\n  let renderArgs;\n\n  try {\n    renderArgs = await getStoreRenderArgs({\n      store,\n      matchContext,\n      resolver,\n    });\n  } catch (e) {\n    if (e.isFoundRedirectException) {\n      res.redirect(302, store.farce.createHref(e.location));\n      return;\n    }\n\n    throw e;\n  }\n\n  res.status(renderArgs.error ? renderArgs.error.status : 200).send(\n    renderPageToString(\n      <Provider store={store}>\n        <RouterProvider renderArgs={renderArgs}>\n          {render(renderArgs)}\n        </RouterProvider>\n      </Provider>,\n      store.getState(),\n    ),\n  );\n});\n```\n\nYou must dispatch `FarceActions.init()` before calling `getStoreRenderArgs`. `getStoreRenderArgs` takes an options object. This object must have the `store` property for your store and the `resolver` property as described above. It supports an optional `matchContext` property as described above as well. `getStoreRenderArgs` returns a promise that resolves to a `renderArgs` object that can be passed into a `render` function as above.\n\nOn the client, pass the value resolved by by `getStoreRenderArgs` to your `<ConnectedRouter>` as the `initialRenderArgs` prop.\n\n```js\nimport { getStoreRenderArgs } from 'found';\n\n/* ... */\n\n(async () => {\n  const initialRenderArgs = await getStoreRenderArgs({\n    store,\n    matchContext,\n    resolver,\n  });\n\n  ReactDOM.render(\n    <Provider store={store}>\n      <ConnectedRouter\n        matchContext={matchContext}\n        resolver={resolver}\n        initialRenderArgs={initialRenderArgs}\n      />\n    </Provider>,\n    document.getElementById('root'),\n  );\n})();\n```\n\n### Minimizing bundle size\n\nThe top-level `found` package exports everything available in this library. It is unlikely that any single application will use all the features available. As such, for real applications, you should import the modules you need directly, to pull in only the code that you use.\n\n```js\nimport createBrowserRouter from 'found/createBrowserRouter';\nimport makeRouteConfig from 'found/makeRouteConfig';\nimport { routerShape } from 'found/PropTypes';\nimport Route from 'found/Route';\n\n// Instead of:\n// import {\n//  createBrowserRouter,\n//  makeRouteConfig,\n//  Route,\n//  routerShape,\n// } from 'found';\n```\n\n[build-badge]: https://img.shields.io/travis/4Catalyzer/found/master.svg\n[build]: https://travis-ci.org/4Catalyzer/found\n[npm-badge]: https://img.shields.io/npm/v/found.svg\n[npm]: https://www.npmjs.org/package/found\n","readmeFilename":"README.md"}