Skip to content

chore: upgrade to React 19 #2775

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
"@testing-library/react": "^16.3.0",
"@types/jest": "^29.4.0",
"@types/mockjs": "^1.0.7",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.3",
"@types/react-router": "^5.1.19",
"@umijs/fabric": "^2.1.0",
"antd": "^5.14.2",
Expand All @@ -64,8 +66,8 @@
"jest-environment-jsdom": "^29.4.1",
"jest-localstorage-mock": "^2.4.18",
"mockjs": "^1.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-drag-listview": "^0.1.6",
"react-router": "^6.4.2",
"react-shadow": "^19.0.3",
Expand All @@ -77,6 +79,10 @@
"webpack-cli": "^5.1.4",
"webpack-merge": "^4.2.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"commitlint": {
"extends": ["@commitlint/config-conventional"]
}
Expand Down
11 changes: 8 additions & 3 deletions packages/hooks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,25 @@
"screenfull": "^5.0.0",
"tslib": "^2.4.1"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"devDependencies": {
"@alifd/next": "^1.20.6",
"@ant-design/icons": "^5.0.1",
"@types/js-cookie": "^3.0.6",
"@types/lodash": "^4.14.202",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.3",
"antd": "^5.2.1",
"jest-websocket-mock": "^2.1.0",
"mockjs": "^1.1.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-drag-listview": "^0.1.6",
"react-json-view": "^1.21.3"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"engines": {
"node": ">=8.0.0"
},
Expand Down
9 changes: 4 additions & 5 deletions packages/hooks/src/createDeepCompareEffect/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { useRef } from 'react';
import React from 'react';
import type { DependencyList, useEffect, useLayoutEffect } from 'react';
import { depsEqual } from '../utils/depsEqual';

type EffectHookType = typeof useEffect | typeof useLayoutEffect;

type CreateUpdateEffect = (hook: EffectHookType) => EffectHookType;

export const createDeepCompareEffect: CreateUpdateEffect = (hook) => (effect, deps) => {
const ref = useRef<DependencyList>();
const signalRef = useRef<number>(0);

const ref = React.useRef<DependencyList | undefined>([]);
const signalRef = React.useRef<number>(0);
if (deps === undefined || !depsEqual(deps, ref.current)) {
signalRef.current += 1;
}
ref.current = deps;

hook(effect, [signalRef.current]);
};
20 changes: 9 additions & 11 deletions packages/hooks/src/useAntdTable/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RenderHookResult } from '@testing-library/react';
import { act, renderHook, waitFor } from '@testing-library/react';
import { sleep } from '../../utils/testingHelpers';
import useAntdTable from '../index';
Expand Down Expand Up @@ -63,15 +64,12 @@ describe('useAntdTable', () => {
searchType = type;
};

const setUp = (service, options) => renderHook((o) => useAntdTable(service, o || options));
const setUp = (
service: Parameters<typeof useAntdTable>[0],
options: Parameters<typeof useAntdTable>[1],
) => renderHook((o) => useAntdTable(service, o || options));

let hook: any;

// afterEach(() => {
// form.resetFields();
// changeSearchType('simple');
// hook?.unmount();
// });
let hook: RenderHookResult<any, any>;

it('should fetch after first render', async () => {
queryArgs = undefined;
Expand Down Expand Up @@ -198,9 +196,9 @@ describe('useAntdTable', () => {
getFieldInstance(key: string) {
// 根据不同的 type 返回不同的 fieldsValues
if (searchType === 'simple') {
return ['name'].includes(key);
return ['name'].includes(key) as any;
}
return ['name', 'email', 'phone'].includes(key);
return ['name', 'email', 'phone'].includes(key) as any;
},
};

Expand Down Expand Up @@ -289,7 +287,7 @@ describe('useAntdTable', () => {
defaultParams: {
current: 1,
pageSize: 10,
},
} as any,
defaultPageSize: 20,
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { act, renderHook } from '@testing-library/react';
import useControllableValue, { Options, Props } from '../index';
import type { Options, Props } from '../index';
import useControllableValue from '../index';

describe('useControllableValue', () => {
const setUp = (props?: Props, options?: Options<any>): any =>
const setUp = (props?: Props, options?: Options<any>) =>
renderHook(() => useControllableValue(props, options));

it('defaultValue should work', () => {
Expand Down
5 changes: 4 additions & 1 deletion packages/hooks/src/useCookieState/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ function useCookieState(cookieKey: string, options: Options = {}) {
const [state, setState] = useState<State>(() => {
const cookieValue = Cookies.get(cookieKey);

if (isString(cookieValue)) return cookieValue;
if (isString(cookieValue)) {
return cookieValue;
}

if (isFunction(options.defaultValue)) {
return options.defaultValue();
Expand All @@ -27,6 +29,7 @@ function useCookieState(cookieKey: string, options: Options = {}) {
newValue: State | ((prevState: State) => State),
newOptions: Cookies.CookieAttributes = {},
) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { defaultValue, ...restOptions } = { ...options, ...newOptions };
const value = isFunction(newValue) ? newValue(state) : newValue;

Expand Down
3 changes: 1 addition & 2 deletions packages/hooks/src/useCountDown/demo/demo1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import React from 'react';
import { useCountDown } from 'ahooks';

export default () => {
const [countdown, formattedRes] = useCountDown({
const [, formattedRes] = useCountDown({
targetDate: `${new Date().getFullYear()}-12-31 23:59:59`,
});
const { days, hours, minutes, seconds, milliseconds } = formattedRes;

return (
<p>
There are {days} days {hours} hours {minutes} minutes {seconds} seconds {milliseconds}{' '}
Expand Down
3 changes: 2 additions & 1 deletion packages/hooks/src/useCounter/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { act, renderHook } from '@testing-library/react';
import useCounter, { Options } from '../index';
import type { Options } from '../index';
import useCounter from '../index';

const setUp = (init?: number, options?: Options) => renderHook(() => useCounter(init, options));

Expand Down
2 changes: 1 addition & 1 deletion packages/hooks/src/useCreation/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('useCreation', () => {
data: number;
}

const setUp = (): any =>
const setUp = () =>
renderHook(() => {
const [count, setCount] = useState(0);
const [, setFlag] = useState({});
Expand Down
10 changes: 6 additions & 4 deletions packages/hooks/src/useCreation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ import type { DependencyList } from 'react';
import { useRef } from 'react';
import depsAreSame from '../utils/depsAreSame';

export default function useCreation<T>(factory: () => T, deps: DependencyList) {
const useCreation = <T>(factory: () => T, deps: DependencyList) => {
const { current } = useRef({
deps,
obj: undefined as undefined | T,
obj: undefined as T,
initialized: false,
});
if (current.initialized === false || !depsAreSame(current.deps, deps)) {
current.deps = deps;
current.obj = factory();
current.initialized = true;
}
return current.obj as T;
}
return current.obj;
};

export default useCreation;
11 changes: 6 additions & 5 deletions packages/hooks/src/useDebounceEffect/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { RenderHookResult } from '@testing-library/react';
import { act, renderHook } from '@testing-library/react';
import useDebounceEffect from '../index';
import { sleep } from '../../utils/testingHelpers';

let hook;
let hook: RenderHookResult<any, any>;

describe('useDebounceEffect', () => {
it('useDebounceEffect should work', async () => {
Expand Down Expand Up @@ -53,7 +54,7 @@ describe('useDebounceEffect', () => {
const mockEffect = jest.fn(() => {});
const mockCleanUp = jest.fn(() => {});

const hook = renderHook(
const hook2 = renderHook(
(props) =>
useDebounceEffect(
() => {
Expand All @@ -71,7 +72,7 @@ describe('useDebounceEffect', () => {
expect(mockEffect.mock.calls.length).toBe(0);
expect(mockCleanUp.mock.calls.length).toBe(0);

hook.rerender(1);
hook2.rerender(1);
await sleep(50);
expect(mockEffect.mock.calls.length).toBe(0);
expect(mockCleanUp.mock.calls.length).toBe(0);
Expand All @@ -82,14 +83,14 @@ describe('useDebounceEffect', () => {
expect(mockEffect.mock.calls.length).toBe(1);
expect(mockCleanUp.mock.calls.length).toBe(0);

hook.rerender(2);
hook2.rerender(2);
await act(async () => {
await sleep(300);
});
expect(mockEffect.mock.calls.length).toBe(2);
expect(mockCleanUp.mock.calls.length).toBe(1);

hook.unmount();
hook2.unmount();
expect(mockEffect.mock.calls.length).toBe(2);
expect(mockCleanUp.mock.calls.length).toBe(2);
});
Expand Down
3 changes: 2 additions & 1 deletion packages/hooks/src/useDebounceFn/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RenderHookResult } from '@testing-library/react';
import { act, renderHook } from '@testing-library/react';
import { sleep } from '../../utils/testingHelpers';
import useDebounceFn from '../index';
Expand All @@ -15,7 +16,7 @@ const debounceFn = (gap: number) => {

const setUp = ({ fn, wait }: ParamsObj) => renderHook(() => useDebounceFn(fn, { wait }));

let hook;
let hook: RenderHookResult<any, any>;

describe('useDebounceFn', () => {
it('run, cancel and flush should work', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/hooks/src/useDrag/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export interface Options {
const useDrag = <T>(data: T, target: BasicTarget, options: Options = {}) => {
const optionsRef = useLatest(options);
const dataRef = useLatest(data);
const imageElementRef = useRef<Element>();
const imageElementRef = useRef<Element>(null);

const { dragImage } = optionsRef.current;

Expand Down
3 changes: 2 additions & 1 deletion packages/hooks/src/useDrop/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { renderHook } from '@testing-library/react';
import useDrop, { Options } from '../index';
import type { Options } from '../index';
import useDrop from '../index';
import type { BasicTarget } from '../../utils/domTarget';

const setup = (target: unknown, options?: Options) =>
Expand Down
4 changes: 2 additions & 2 deletions packages/hooks/src/useDrop/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const useDrop = (target: BasicTarget, options: Options = {}) => {
const optionsRef = useLatest(options);

// https://stackoverflow.com/a/26459269
const dragEnterTarget = useRef<any>();
const dragEnterTarget = useRef<EventTarget>(null);

useEffectWithTarget(
() => {
Expand All @@ -40,7 +40,7 @@ const useDrop = (target: BasicTarget, options: Options = {}) => {
let data = dom;
try {
data = JSON.parse(dom);
} catch (e) {
} catch {
data = dom;
}
optionsRef.current.onDom(data, event as React.DragEvent);
Expand Down
2 changes: 1 addition & 1 deletion packages/hooks/src/useEventEmitter/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useState } from 'react';
import useEventEmitter from '../index';

describe('useEventEmitter', () => {
const setUp = (): any =>
const setUp = () =>
renderHook(() => {
const event$ = useEventEmitter<number>();
const [count, setCount] = useState(0);
Expand Down
8 changes: 5 additions & 3 deletions packages/hooks/src/useEventEmitter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class EventEmitter<T> {

useSubscription = (callback: Subscription<T>) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const callbackRef = useRef<Subscription<T>>();
const callbackRef = useRef<Subscription<T>>(null);
callbackRef.current = callback;
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
Expand All @@ -30,10 +30,12 @@ export class EventEmitter<T> {
};
}

export default function useEventEmitter<T = void>() {
const ref = useRef<EventEmitter<T>>();
function useEventEmitter<T = void>() {
const ref = useRef<EventEmitter<T>>(null);
if (!ref.current) {
ref.current = new EventEmitter();
}
return ref.current;
}

export default useEventEmitter;
4 changes: 2 additions & 2 deletions packages/hooks/src/useExternal/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const loadCss: LoadExternal = (path, props = {}) => {
const useExternal = (path?: string, options?: Options) => {
const [status, setStatus] = useState<Status>(path ? 'loading' : 'unset');

const ref = useRef<Element>();
const ref = useRef<Element>(null);

useEffect(() => {
if (!path) {
Expand Down Expand Up @@ -147,7 +147,7 @@ const useExternal = (path?: string, options?: Options) => {
ref.current?.remove();
}

ref.current = undefined;
ref.current = null;
};
}, [path]);

Expand Down
10 changes: 7 additions & 3 deletions packages/hooks/src/useFavicon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ type ImgTypes = keyof typeof ImgTypeMap;

const useFavicon = (href: string) => {
useEffect(() => {
if (!href) return;
if (!href) {
return;
}

const cutUrl = href.split('.');

const imgSuffix = cutUrl[cutUrl.length - 1].toLocaleUpperCase() as ImgTypes;

const link: HTMLLinkElement =
document.querySelector("link[rel*='icon']") || document.createElement('link');
const link =
document.querySelector<HTMLLinkElement>("link[rel*='icon']") ||
document.createElement('link');

link.type = ImgTypeMap[imgSuffix];
link.href = href;
Expand Down
Loading
Loading