Skip to content

Commit d4df5a6

Browse files
authored
feat: add support for React Router 6 stable (#268)
1 parent c12b9d0 commit d4df5a6

File tree

7 files changed

+5971
-4603
lines changed

7 files changed

+5971
-4603
lines changed

.eslintrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"extends": "airbnb",
3-
"parser": "babel-eslint",
2+
"extends": ["@react-bootstrap", "prettier"],
3+
"plugins": ["prettier"],
44
"rules": {
55
"react/jsx-filename-extension": "off",
66
"import/no-extraneous-dependencies": "off",

package-lock.json

Lines changed: 5766 additions & 4386 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
"build": "rimraf lib && webpack-cli",
1212
"lint": "eslint src test *.js",
1313
"release": "release",
14-
"tdd": "karma start",
14+
"tdd": "jest --watch",
1515
"test": "npm run lint && jest",
16-
"visual-test": "open http://localhost:8080/ && webpack-dev-server --config webpack.visual.config.babel.js"
16+
"visual-test": "webpack-dev-server --config webpack.visual.config.babel.js --open"
1717
},
1818
"repository": {
1919
"type": "git",
@@ -37,41 +37,48 @@
3737
"react": ">=16.13.1",
3838
"react-router-dom": ">=6.0.0"
3939
},
40+
"prettier": {
41+
"singleQuote": true,
42+
"trailingComma": "all"
43+
},
4044
"devDependencies": {
41-
"@babel/core": "^7.11.4",
42-
"@babel/preset-env": "^7.11.0",
43-
"@babel/preset-react": "^7.10.4",
45+
"@babel/cli": "^7.16.0",
46+
"@babel/core": "^7.16.0",
47+
"@babel/preset-env": "^7.16.4",
48+
"@babel/preset-react": "^7.16.0",
49+
"@react-bootstrap/eslint-config": "^1.3.2",
4450
"babel-eslint": "^10.1.0",
45-
"babel-jest": "^26.3.0",
46-
"babel-loader": "^8.1.0",
47-
"bootstrap": "^4.5.2",
48-
"chai": "^4.2.0",
51+
"babel-jest": "^26.6.3",
52+
"babel-loader": "^8.2.3",
53+
"bootstrap": "^4.6.1",
54+
"chai": "^4.3.4",
4955
"colors": "^1.4.0",
50-
"css-loader": "^4.2.2",
56+
"css-loader": "^4.3.0",
5157
"enzyme": "^3.11.0",
52-
"enzyme-adapter-react-16": "^1.15.3",
53-
"eslint": "^7.7.0",
54-
"eslint-config-airbnb": "^18.2.0",
58+
"enzyme-adapter-react-16": "^1.15.6",
59+
"eslint": "^7.32.0",
5560
"eslint-plugin-babel": "^5.3.1",
56-
"eslint-plugin-import": "^2.22.0",
57-
"eslint-plugin-jsx-a11y": "^6.3.1",
58-
"eslint-plugin-react": "^7.20.6",
59-
"file-loader": "^6.0.0",
60-
"history": "^5.0.0",
61-
"html-webpack-plugin": "^4.3.0",
61+
"eslint-plugin-import": "^2.25.3",
62+
"eslint-plugin-jsx-a11y": "^6.5.1",
63+
"eslint-plugin-prettier": "^4.0.0",
64+
"eslint-plugin-react": "^7.27.0",
65+
"file-loader": "^6.2.0",
66+
"history": "^5.1.0",
67+
"html-webpack-plugin": "^4.5.2",
6268
"jasmine-enzyme": "^7.1.2",
63-
"jest": "^26.4.2",
64-
"lodash": "^4.17.20",
65-
"react": "^16.13.1",
66-
"react-bootstrap": "^1.3.0",
67-
"react-dom": "^16.13.1",
68-
"react-router-dom": "^6.0.0-beta.0",
69+
"jest": "^26.6.3",
70+
"lodash": "^4.17.21",
71+
"prettier": "^2.4.1",
72+
"react": "^16.14.0",
73+
"react-bootstrap": "^1.6.4",
74+
"react-dom": "^16.14.0",
75+
"react-router-dom": "^6.0.2",
6976
"rimraf": "^3.0.2",
70-
"style-loader": "^1.2.1",
71-
"url-loader": "^4.1.0",
72-
"webpack": "^4.44.1",
77+
"style-loader": "^1.3.0",
78+
"url-loader": "^4.1.1",
79+
"webpack": "^4.46.0",
7380
"webpack-cli": "^3.3.12",
74-
"webpack-dev-server": "^3.11.0",
81+
"webpack-dev-server": "^3.11.3",
7582
"yargs": "^15.4.1"
7683
},
7784
"dependencies": {

src/LinkContainer.js

Lines changed: 41 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
33
import {
4-
Route, useHref, useLocation, useMatch, useNavigate,
4+
useHref,
5+
useLocation,
6+
useMatch,
7+
useNavigate,
58
} from 'react-router-dom';
69
import { isFunction } from 'lodash';
710

8-
const isModifiedEvent = (event) => !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
11+
const isModifiedEvent = (event) =>
12+
!!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
913

1014
const LinkContainer = ({
1115
children,
@@ -20,8 +24,19 @@ const LinkContainer = ({
2024
// eslint-disable-next-line comma-dangle
2125
...props
2226
}) => {
27+
const path = typeof to === 'object' ? to.pathname : to;
2328
const navigate = useNavigate();
2429
const href = useHref(typeof to === 'string' ? { pathname: to } : to);
30+
const match = useMatch(path);
31+
const location = useLocation();
32+
const child = React.Children.only(children);
33+
34+
const isActive = !!(getIsActive
35+
? isFunction(getIsActive)
36+
? getIsActive(match, location)
37+
: getIsActive
38+
: match);
39+
2540
const handleClick = (event) => {
2641
if (children.props.onClick) {
2742
children.props.onClick(event);
@@ -32,9 +47,9 @@ const LinkContainer = ({
3247
}
3348

3449
if (
35-
!event.defaultPrevented // onClick prevented default
36-
&& event.button === 0 // ignore right clicks
37-
&& !isModifiedEvent(event) // ignore clicks with modifier keys
50+
!event.defaultPrevented && // onClick prevented default
51+
event.button === 0 && // ignore right clicks
52+
!isModifiedEvent(event) // ignore clicks with modifier keys
3853
) {
3954
event.preventDefault();
4055

@@ -44,56 +59,35 @@ const LinkContainer = ({
4459
}
4560
};
4661

47-
const child = React.Children.only(children);
48-
const path = typeof to === 'object' ? to.pathname : to;
49-
const InnerRouteElement = () => {
50-
const match = useMatch(path);
51-
const location = useLocation();
52-
const isActive = !!(getIsActive ? (isFunction(getIsActive) ? getIsActive(match, location) : getIsActive) : match);
53-
54-
return React.cloneElement(
55-
child,
56-
{
57-
...props,
58-
className: [className, child.props.className, isActive ? activeClassName : null]
59-
.join(' ').trim(),
60-
style: isActive ? { ...style, ...activeStyle } : style,
61-
href,
62-
onClick: handleClick,
63-
},
64-
);
65-
};
66-
67-
return (
68-
<Route
69-
path={path}
70-
element={<InnerRouteElement />}
71-
/>
72-
);
62+
return React.cloneElement(child, {
63+
...props,
64+
className: [
65+
className,
66+
child.props.className,
67+
isActive ? activeClassName : null,
68+
]
69+
.join(' ')
70+
.trim(),
71+
style: isActive ? { ...style, ...activeStyle } : style,
72+
href,
73+
onClick: handleClick,
74+
});
7375
};
7476

7577
LinkContainer.propTypes = {
7678
children: PropTypes.element.isRequired,
7779
onClick: PropTypes.func,
7880
replace: PropTypes.bool,
79-
to: PropTypes.oneOfType([
80-
PropTypes.string,
81-
PropTypes.object,
82-
]).isRequired,
81+
to: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
8382
className: PropTypes.string,
8483
activeClassName: PropTypes.string,
85-
style: PropTypes.objectOf(PropTypes.oneOfType([
86-
PropTypes.string,
87-
PropTypes.number,
88-
])),
89-
activeStyle: PropTypes.objectOf(PropTypes.oneOfType([
90-
PropTypes.string,
91-
PropTypes.number,
92-
])),
93-
isActive: PropTypes.oneOfType([
94-
PropTypes.func,
95-
PropTypes.bool,
96-
]),
84+
style: PropTypes.objectOf(
85+
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
86+
),
87+
activeStyle: PropTypes.objectOf(
88+
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
89+
),
90+
isActive: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
9791
};
9892

9993
LinkContainer.defaultProps = {

0 commit comments

Comments
 (0)