├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── package.json ├── src └── use-react-router.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /use-react-router.d.ts 3 | /use-react-router.js 4 | /use-react-router.js.map 5 | /yarn.lock 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /.git 2 | /node_modules 3 | /src 4 | /.gitignore 5 | /.npmignore 6 | /.travis.yml 7 | /package-lock.json 8 | /tsconfig.json 9 | /yarn.lock 10 | /yarn-error.log 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 8.9.1 3 | branches: 4 | only: master 5 | cache: yarn 6 | install: yarn 7 | script: 8 | - yarn build 9 | deploy: 10 | api_key: 11 | secure: FX+eD+sJf2FsSKfyFZUyBnotcUsHllaupFfwGruw7aALf7Um3gXQJQ2jAeFZWgz6jDPLPNPkOXAxYgkDtebEtavbmCOsE1p6RGeStf9O4FdpWpHGiEolzIyVVR15m8lcyBMB4nsK6nmb650FlUISHEVuSWIhAQxw0+dpk4qDcRmzjdYPxNLaH2CVme5Ses2rb+C/jr5nuvyu3oJlZIF6z1X+ieDtV9BOswbKjqRrV9Bjt/P0kKoxyng8J/5l9g0um317pekzqhuWBhVM7dAEwL6Rm3H6QhNkYfiSFn747InqbnNTBi9o7SCYp9inxIh4i6XL5JIAqpnGity6ECGYlf2pzmuV5WhZlAnJimIFuAKXNY9vKnscz5kvwvFWVuzkASD8yZiehzJGZMnaCFxz3wgyUHInqqOUGLUfKTA2S1VEDt8oSVWTG+d8BlB2JRdo56yjqNAtfIc8uYcpEaaXE0sopiPnE/CEhVM8MjeAa0+lRFNyR82suXDxx0eeo68qKZQ7CKm8S45gzdo3i7jvpLP6VHTcUaKxIMmD38Yii83crs15dCLoDh8oOIPnOHh1DWaNuGEomKZm3KHw/UdpMReoRdkmluY2r6bYfBPAeEJ3KyKWBjfSOzAl9whq2Ajaksmw1RTsg/oDIJ+d3di7wlUMSUQlH8Np9/gNi5J7dt8= 12 | email: npmjs@charlesstover.com 13 | on: 14 | branch: master 15 | provider: npm 16 | skip_cleanup: true 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Charles Stover 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # useReactRouter 2 | 3 | [![version](https://img.shields.io/npm/v/use-react-router.svg)](https://www.npmjs.com/package/use-react-router) 4 | [![downloads](https://img.shields.io/npm/dt/use-react-router.svg)](https://www.npmjs.com/package/use-react-router) 5 | [![minzipped size](https://img.shields.io/bundlephobia/minzip/use-react-router.svg)](https://www.npmjs.com/package/use-react-router) 6 | 7 | `useReactRouter` is a React Hook that provides pub-sub behavior for `react-router`. 8 | Unlike the `withRouter` Higher-Order Component, `useReactRouter` will re-render your component when the location changes! 9 | 10 | `useReactRouter()` returns an object that contains the `history`, `location`, and `match` properties that would be passed as props by the HOC. 11 | 12 | A tutorial covering the design and development of this package can be found on Medium: [How to Convert withRouter to a React Hook](https://medium.com/@Charles_Stover/how-to-convert-withrouter-to-a-react-hook-19bb02a29ed6). 13 | 14 | ## Why Pub-Sub? 15 | 16 | Pub-sub behavior is a common request (that's commonly rejected) for the `react-router` package. 17 | 18 | For users who adamently prefer pub-sub behavior over `react-router`'s suggested alternatives, this package offers a solution. 19 | 20 | A non-pub-sub React Hook is anticipated to eventually be included in the `react-router` package itself. 21 | 22 | ## Install 23 | 24 | **You must be using `react-router` and `react-router-dom` v5.0.0 or greater.** 25 | 26 | * `npm install use-react-router` or 27 | * `yarn add use-react-router` 28 | 29 | ## Use 30 | 31 | Import `useReactRouter` and use it as a React Hook. 32 | 33 | ```JavaScript 34 | import useReactRouter from 'use-react-router'; 35 | 36 | const MyPath = () => { 37 | const { history, location, match } = useReactRouter(); 38 | return ( 39 |
40 | My location is {location.pathname}! 41 |
42 | ); 43 | }; 44 | ``` 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "use-react-router", 3 | "version": "1.0.7", 4 | "author": "Charles Stover ", 5 | "description": "React Hook for pub-sub behavior using React Router.", 6 | "homepage": "https://github.com/CharlesStover/use-react-router#readme", 7 | "license": "MIT", 8 | "main": "use-react-router.js", 9 | "types": "use-react-router.d.ts", 10 | "repository": "https://github.com/CharlesStover/use-react-router.git", 11 | "bugs": { 12 | "url": "https://github.com/CharlesStover/use-react-router/issues" 13 | }, 14 | "files": [ 15 | "use-react-router.d.ts", 16 | "use-react-router.js" 17 | ], 18 | "scripts": { 19 | "build": "tsc", 20 | "prepublishOnly": "npm run build" 21 | }, 22 | "dependencies": { 23 | "use-force-update": "^1.0.5" 24 | }, 25 | "devDependencies": { 26 | "@types/react": "^16.4.18", 27 | "@types/react-router": "^5.0.1", 28 | "react": "^16.8.0", 29 | "react-router": "^5.0.0", 30 | "typescript": "^3.1.3" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.8.0", 34 | "react-router": "^5.0.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/use-react-router.ts: -------------------------------------------------------------------------------- 1 | import { LocationState } from 'history'; 2 | import { Context, useContext, useEffect } from 'react'; 3 | import { __RouterContext, RouteComponentProps, StaticContext } from 'react-router'; 4 | import useForceUpdate from 'use-force-update'; 5 | 6 | type AnyContext = Context>; 7 | 8 | const INCORRECT_VERSION_ERROR: Error = 9 | new Error('use-react-router may only be used with react-router@^5.'); 10 | 11 | const MISSING_CONTEXT_ERROR: Error = 12 | new Error('useReactRouter may only be called within a context.'); 13 | 14 | export default function useRouter< 15 | P extends { [K in keyof P]?: string } = {}, 16 | C extends StaticContext = StaticContext, 17 | S = LocationState, 18 | >(): RouteComponentProps { 19 | 20 | // If this version of react-router does not support Context, 21 | if (!__RouterContext) { 22 | throw INCORRECT_VERSION_ERROR; 23 | } 24 | 25 | // If the react-router Context is not a parent Component, 26 | const context: RouteComponentProps = 27 | useContext>( 28 | __RouterContext as AnyContext as Context>, 29 | ); 30 | if (!context) { 31 | throw MISSING_CONTEXT_ERROR; 32 | } 33 | 34 | const forceUpdate: VoidFunction = useForceUpdate(); 35 | useEffect( 36 | (): VoidFunction => 37 | context.history.listen(forceUpdate), 38 | [ context ], 39 | ); 40 | return context; 41 | } 42 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "downlevelIteration": true, 5 | "lib": [ "dom", "es5", "es2015", "scripthost" ], 6 | "module": "commonjs", 7 | "moduleResolution": "Node", 8 | "noFallthroughCasesInSwitch": true, 9 | "noImplicitAny": true, 10 | "noImplicitReturns": true, 11 | "noImplicitThis": true, 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "outDir": ".", 15 | "removeComments": true, 16 | "sourceMap": false, 17 | "strict": true, 18 | "strictNullChecks": true, 19 | "strictPropertyInitialization": true, 20 | "target": "es5" 21 | }, 22 | "files": [ "src/use-react-router.ts" ] 23 | } 24 | --------------------------------------------------------------------------------