Skip to content

Commit a550bd7

Browse files
feat: add support for React 17, 18, and 19
BREAKING CHANGE: Drop support for React 16 - Replace UISref.defaultProps with default parameters (React 19 compat) - Update deprecated types: StatelessComponent -> FunctionComponent - Remove ValidationMap cast, ClassicComponentClass usage - Import act from 'react' instead of 'react-dom/test-utils' - Update @testing-library/react to v16 (supports React 18/19)
1 parent c6c8992 commit a550bd7

File tree

10 files changed

+103
-202
lines changed

10 files changed

+103
-202
lines changed

package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,23 +49,24 @@
4949
"prop-types": "^15.8.1"
5050
},
5151
"peerDependencies": {
52-
"react": ">=16.8.0"
52+
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
5353
},
5454
"devDependencies": {
55+
"@testing-library/dom": "^10",
5556
"@testing-library/jest-dom": "^6.9.1",
56-
"@testing-library/react": "^12.0.0",
57+
"@testing-library/react": "^16",
5758
"@types/prop-types": "^15.7.15",
58-
"@types/react": "17.0.14",
59-
"@types/react-dom": "17.0.9",
59+
"@types/react": "^19",
60+
"@types/react-dom": "^19",
6061
"@uirouter/publish-scripts": "^2.7.0",
6162
"@vitest/ui": "^4.0.16",
6263
"cross-env": "^10.1.0",
6364
"husky": "^9.1.7",
6465
"jsdom": "^27.4.0",
6566
"prettier": "^3.7.4",
6667
"pretty-quick": "^4.2.2",
67-
"react": "^17.0.2",
68-
"react-dom": "^17.0.2",
68+
"react": "^19",
69+
"react-dom": "^19",
6970
"ts-loader": "^9.5.4",
7071
"tsconfig-paths-webpack-plugin": "^4.2.0",
7172
"typescript": "^5.9.3",

src/__tests__/util.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import * as React from 'react';
2+
import { act } from 'react';
23
import { describe, expect, it, vi } from 'vitest';
34
import { TransitionOptions, RawParams, StateOrName, TransitionPromise, memoryLocationPlugin } from '@uirouter/core';
45
import { render } from '@testing-library/react';
5-
import { act } from 'react-dom/test-utils';
66
import { UIRouterReact } from '../core';
77
import { servicesPlugin, UIRouter } from '../index';
88
import { ReactStateDeclaration } from '../interface';

src/components/UIRouter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export const InstanceOrPluginsMissingError = `Router instance or plugins missing
132132
* ```
133133
*/
134134
export function UIRouter(props: UIRouterProps) {
135-
const uiRouter = useRef<UIRouterReact>();
135+
const uiRouter = useRef<UIRouterReact>(undefined);
136136
const [started, setStarted] = useState<boolean>(false);
137137

138138
useEffect(() => {

src/components/UISref.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export interface UISrefProps {
5050
* - the underlying tag (e.g.: anchor tag) has a 'target' attribute, such as `<a target="_blank">Open in new window</a>`
5151
* - preventDefault has been called on the event, e.g.: `<a onClick={e => e.preventDefault()}>no-op</a>`
5252
*/
53-
export const UISref: React.FC<UISrefProps> = ({ children, className, options, params, to }) => {
53+
export const UISref: React.FC<UISrefProps> = ({ children, className = null, options = {}, params = {}, to }) => {
5454
const { onClick, href } = useSref(to, params, options);
5555
const childrenProps = children.props;
5656

@@ -88,9 +88,3 @@ UISref.propTypes = {
8888
options: PropTypes.object,
8989
className: PropTypes.string,
9090
};
91-
92-
UISref.defaultProps = {
93-
params: {},
94-
options: {},
95-
className: null,
96-
};

src/components/UIView.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import * as PropTypes from 'prop-types';
22
import * as React from 'react';
33
import {
44
ComponentType,
5+
FunctionComponent,
56
ReactNode,
6-
ValidationMap,
77
cloneElement,
88
createContext,
99
createElement,
@@ -15,6 +15,7 @@ import {
1515
forwardRef,
1616
useImperativeHandle,
1717
useRef,
18+
JSX,
1819
} from 'react';
1920
import {
2021
ActiveUIView,
@@ -129,7 +130,7 @@ function useRoutedComponentProps(
129130
router: UIRouter,
130131
stateName: string,
131132
viewConfig: ViewConfig,
132-
component: React.FunctionComponent<any> | React.ComponentClass<any> | React.ClassicComponentClass<any>,
133+
component: FunctionComponent<any> | React.ComponentClass<any>,
133134
resolves: TypedMap<any> | {},
134135
className: string,
135136
style: Object,
@@ -190,7 +191,7 @@ function useReactHybridApi(ref: React.Ref<unknown>, uiViewData: ActiveUIView, ui
190191
*/
191192
function useUiCanExitClassComponentHook(router: UIRouter, stateName: string, maybeComponentClass: any) {
192193
// Use refs and run the callback outside of any render pass
193-
const componentInstanceRef = useRef<any>();
194+
const componentInstanceRef = useRef<any>(undefined);
194195
const deregisterRef = useRef<Function>(() => undefined);
195196

196197
function callbackRef(componentInstance) {
@@ -278,7 +279,7 @@ View.propTypes = {
278279
className: PropTypes.string,
279280
style: PropTypes.object,
280281
render: PropTypes.func,
281-
} as ValidationMap<UIViewProps>;
282+
};
282283

283284
/**
284285
* UIView Viewport

src/components/__tests__/UIRouter.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { memoryLocationPlugin } from '../../index';
88
import { muteConsoleErrors } from '../../__tests__/util';
99

1010
class Child extends React.Component<any, any> {
11-
static propTypes: React.ValidationMap<any> = {
11+
static propTypes = {
1212
router: PropTypes.object,
1313
};
1414
render() {

src/components/__tests__/UIView.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { beforeEach, describe, expect, it, vi } from 'vitest';
22
import { render } from '@testing-library/react';
33
import * as React from 'react';
4-
import { act } from 'react-dom/test-utils';
4+
import { act } from 'react';
55
import { Transition } from '@uirouter/core';
66

77
import { makeTestRouter, muteConsoleErrors } from '../../__tests__/util';
@@ -90,7 +90,7 @@ describe('<UIView>', () => {
9090
});
9191

9292
describe('injects the right props:', () => {
93-
let lastProps = undefined;
93+
let lastProps: any = undefined;
9494
const Comp = (props) => {
9595
lastProps = props;
9696
return <span>component</span>;

src/hooks/__tests__/useSref.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { beforeEach, describe, expect, it, vi } from 'vitest';
22
import { fireEvent, render } from '@testing-library/react';
33
import * as React from 'react';
4-
import { act } from 'react-dom/test-utils';
4+
import { act } from 'react';
55
import { makeTestRouter, muteConsoleErrors } from '../../__tests__/util';
66
import { UIRouter, UIView } from '../../components';
77
import { UISrefActive, UISrefActiveContext } from '../../components/UISrefActive';

src/interface.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { StatelessComponent, ComponentClass, ClassicComponentClass } from 'react';
1+
import { FunctionComponent, ComponentClass } from 'react';
22
import { StateDeclaration, _ViewDeclaration, Transition } from '@uirouter/core';
33

44
/**
@@ -169,7 +169,7 @@ export interface ReactViewDeclaration extends _ViewDeclaration {
169169
* }
170170
* ```
171171
*/
172-
component?: StatelessComponent<any> | ComponentClass<any> | ClassicComponentClass<any>;
172+
component?: FunctionComponent<any> | ComponentClass<any>;
173173

174174
/**
175175
* @hidden

0 commit comments

Comments
 (0)