@reactuses/core 5.0.23-beta.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -13,12 +13,6 @@ var React__default = /*#__PURE__*/_interopDefault(React);
13
13
  var Cookies__default = /*#__PURE__*/_interopDefault(Cookies);
14
14
  var screenfull__default = /*#__PURE__*/_interopDefault(screenfull);
15
15
 
16
- const useLatest = (value)=>{
17
- const ref = React.useRef(value);
18
- ref.current = value;
19
- return ref;
20
- };
21
-
22
16
  var _window_navigator, _window;
23
17
  function isFunction(val) {
24
18
  return typeof val === 'function';
@@ -32,6 +26,18 @@ const isNavigator = typeof navigator !== 'undefined';
32
26
  function noop() {}
33
27
  const isIOS = isBrowser && ((_window = window) == null ? void 0 : (_window_navigator = _window.navigator) == null ? void 0 : _window_navigator.userAgent) && /iP(?:ad|hone|od)/.test(window.navigator.userAgent);
34
28
 
29
+ const useIsomorphicLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect;
30
+
31
+ const useLatest = (value)=>{
32
+ const ref = React.useRef(value);
33
+ useIsomorphicLayoutEffect(()=>{
34
+ ref.current = value;
35
+ }, [
36
+ value
37
+ ]);
38
+ return ref;
39
+ };
40
+
35
41
  function on(obj, ...args) {
36
42
  if (obj && obj.addEventListener) {
37
43
  obj.addEventListener(...args);
@@ -43,6 +49,7 @@ function off(obj, ...args) {
43
49
  }
44
50
  }
45
51
  const defaultWindow = isBrowser ? window : undefined;
52
+ const defaultDocument = isBrowser ? document : undefined;
46
53
 
47
54
  const defaultOptions$1 = {};
48
55
  function defaultOnError(e) {
@@ -67,6 +74,12 @@ function getTargetElement(target, defaultElement) {
67
74
  return targetElement;
68
75
  }
69
76
 
77
+ const updateReducer = (num)=>(num + 1) % 1000000;
78
+ function useUpdate() {
79
+ const [, update] = React.useReducer(updateReducer, 0);
80
+ return update;
81
+ }
82
+
70
83
  const useCustomCompareEffect = (effect, deps, depsEqual)=>{
71
84
  if (process.env.NODE_ENV !== 'production') {
72
85
  if (!Array.isArray(deps) || !deps.length) {
@@ -77,9 +90,16 @@ const useCustomCompareEffect = (effect, deps, depsEqual)=>{
77
90
  }
78
91
  }
79
92
  const ref = React.useRef(undefined);
80
- if (!ref.current || !depsEqual(deps, ref.current)) {
93
+ const forceUpdate = useUpdate();
94
+ if (!ref.current) {
81
95
  ref.current = deps;
82
96
  }
97
+ useIsomorphicLayoutEffect(()=>{
98
+ if (!depsEqual(deps, ref.current)) {
99
+ ref.current = deps;
100
+ forceUpdate();
101
+ }
102
+ });
83
103
  // eslint-disable-next-line react-hooks/exhaustive-deps
84
104
  React.useEffect(effect, ref.current);
85
105
  };
@@ -133,8 +153,8 @@ const useActiveElement = ()=>{
133
153
  var _window;
134
154
  setActive((_window = window) == null ? void 0 : _window.document.activeElement);
135
155
  }, []);
136
- useEventListener('blur', listener, ()=>window, true);
137
- useEventListener('focus', listener, ()=>window, true);
156
+ useEventListener('blur', listener, defaultWindow, true);
157
+ useEventListener('focus', listener, defaultWindow, true);
138
158
  useMount(()=>{
139
159
  var _window;
140
160
  setActive((_window = window) == null ? void 0 : _window.document.activeElement);
@@ -288,8 +308,6 @@ const useCookie = (key, options = defaultOptions$1, defaultValue)=>{
288
308
  ];
289
309
  };
290
310
 
291
- const useIsomorphicLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect;
292
-
293
311
  /**
294
312
  * keep function reference immutable
295
313
  */ const useEvent = (fn)=>{
@@ -695,11 +713,11 @@ function useStorage(key, defaultValue, getStorage = ()=>isBrowser ? sessionStora
695
713
  ];
696
714
  }
697
715
 
716
+ function value() {
717
+ return window.matchMedia('(prefers-color-scheme: dark)').matches;
718
+ }
698
719
  const useDarkMode = (options)=>{
699
720
  const { selector = 'html', attribute = 'class', classNameDark = '', classNameLight = '', storageKey = 'reactuses-color-scheme', storage = ()=>isBrowser ? localStorage : undefined, defaultValue = false } = options;
700
- const value = ()=>{
701
- return window.matchMedia('(prefers-color-scheme: dark)').matches;
702
- };
703
721
  const [dark, setDark] = useStorage(storageKey, defaultValue, storage, {
704
722
  mountStorageValue: value
705
723
  });
@@ -2168,7 +2186,7 @@ const useMouse = (target)=>{
2168
2186
  newState.elementH = height;
2169
2187
  }
2170
2188
  setState(newState);
2171
- }, ()=>document);
2189
+ }, defaultDocument);
2172
2190
  return state;
2173
2191
  };
2174
2192
 
@@ -2465,24 +2483,24 @@ function usePreferredDark(defaultState) {
2465
2483
  return useMediaQuery('(prefers-color-scheme: dark)', defaultState);
2466
2484
  }
2467
2485
 
2468
- function usePrevious(state) {
2469
- const ref = React.useRef();
2470
- React.useEffect(()=>{
2471
- ref.current = state;
2472
- });
2473
- return ref.current;
2486
+ // Following these issues I think this is the best way to implement usePrevious:
2487
+ // https://github.com/childrentime/reactuse/issues/115
2488
+ // https://github.com/streamich/react-use/issues/2605
2489
+ // https://github.com/alibaba/hooks/issues/2162
2490
+ function usePrevious(value) {
2491
+ const [current, setCurrent] = React.useState(value);
2492
+ const [previous, setPrevious] = React.useState();
2493
+ if (value !== current) {
2494
+ setPrevious(current);
2495
+ setCurrent(value);
2496
+ }
2497
+ return previous;
2474
2498
  }
2475
2499
 
2476
2500
  function useReducedMotion(defaultState) {
2477
2501
  return useMediaQuery('(prefers-reduced-motion: reduce)', defaultState);
2478
2502
  }
2479
2503
 
2480
- const updateReducer = (num)=>(num + 1) % 1000000;
2481
- function useUpdate() {
2482
- const [, update] = React.useReducer(updateReducer, 0);
2483
- return update;
2484
- }
2485
-
2486
2504
  const topVarName = '--reactuse-safe-area-top';
2487
2505
  const rightVarName = '--reactuse-safe-area-right';
2488
2506
  const bottomVarName = '--reactuse-safe-area-bottom';
@@ -3844,7 +3862,7 @@ function _object_without_properties_loose(source, excluded) {
3844
3862
  const useFetchEventSource = (url, options = {})=>{
3845
3863
  const [data, setData] = React.useState(null);
3846
3864
  const [error, setError] = React.useState(null);
3847
- const [status, setStatus] = React.useState("DISCONNECTED");
3865
+ const [status, setStatus] = React.useState('DISCONNECTED');
3848
3866
  const [event, setEvent] = React.useState(null);
3849
3867
  const [lastEventId, setLastEventId] = React.useState(null);
3850
3868
  const retries = React.useRef(0);
@@ -3856,13 +3874,13 @@ const useFetchEventSource = (url, options = {})=>{
3856
3874
  explicitlyClosed.current = true;
3857
3875
  (_abortController_current = abortController.current) == null ? void 0 : _abortController_current.abort();
3858
3876
  abortController.current = null;
3859
- setStatus("DISCONNECTED");
3877
+ setStatus('DISCONNECTED');
3860
3878
  options.onClose == null ? void 0 : options.onClose.call(options);
3861
3879
  }
3862
3880
  });
3863
3881
  const open = useEvent(/*#__PURE__*/ _async_to_generator(function*() {
3864
3882
  close();
3865
- setStatus("CONNECTING");
3883
+ setStatus('CONNECTING');
3866
3884
  explicitlyClosed.current = false;
3867
3885
  retries.current = 0;
3868
3886
  // 创建新的 AbortController
@@ -3881,20 +3899,20 @@ const useFetchEventSource = (url, options = {})=>{
3881
3899
  ]);
3882
3900
  // 构建请求配置
3883
3901
  const finalOptions = _extends({
3884
- method: options.method || "GET",
3902
+ method: options.method || 'GET',
3885
3903
  headers: _extends({
3886
- Accept: "text/event-stream",
3887
- "Cache-Control": "no-cache",
3888
- Connection: "keep-alive"
3904
+ 'Accept': 'text/event-stream',
3905
+ 'Cache-Control': 'no-cache',
3906
+ 'Connection': 'keep-alive'
3889
3907
  }, options.headers),
3890
3908
  signal: abortController.current.signal,
3891
- credentials: withCredentials ? "include" : "same-origin"
3909
+ credentials: withCredentials ? 'include' : 'same-origin'
3892
3910
  }, fetchOptions);
3893
3911
  // 只在 POST 请求时添加 body
3894
- if (options.method === "POST" && body) {
3912
+ if (options.method === 'POST' && body) {
3895
3913
  finalOptions.body = body;
3896
3914
  finalOptions.headers = _extends({}, finalOptions.headers, {
3897
- "Content-Type": "application/json"
3915
+ 'Content-Type': 'application/json'
3898
3916
  });
3899
3917
  }
3900
3918
  yield fetchEventSource.fetchEventSource(url.toString(), _extends({}, finalOptions, {
@@ -3902,7 +3920,7 @@ const useFetchEventSource = (url, options = {})=>{
3902
3920
  onopen (response) {
3903
3921
  return _async_to_generator(function*() {
3904
3922
  if (response.ok) {
3905
- setStatus("CONNECTED");
3923
+ setStatus('CONNECTED');
3906
3924
  setError(null);
3907
3925
  options.onOpen == null ? void 0 : options.onOpen.call(options);
3908
3926
  } else {
@@ -3923,12 +3941,12 @@ const useFetchEventSource = (url, options = {})=>{
3923
3941
  },
3924
3942
  onerror (err) {
3925
3943
  setError(err);
3926
- setStatus("DISCONNECTED");
3944
+ setStatus('DISCONNECTED');
3927
3945
  const retryDelay = options.onError == null ? void 0 : options.onError.call(options, err);
3928
3946
  if (options.autoReconnect && !explicitlyClosed.current) {
3929
3947
  const { retries: maxRetries = -1, delay = 1000, onFailed } = options.autoReconnect;
3930
3948
  retries.current += 1;
3931
- if (typeof maxRetries === "number" && (maxRetries < 0 || retries.current < maxRetries) || typeof maxRetries === "function" && maxRetries()) {
3949
+ if (typeof maxRetries === 'number' && (maxRetries < 0 || retries.current < maxRetries) || typeof maxRetries === 'function' && maxRetries()) {
3932
3950
  return retryDelay != null ? retryDelay : delay;
3933
3951
  } else {
3934
3952
  onFailed == null ? void 0 : onFailed();
@@ -3939,7 +3957,7 @@ const useFetchEventSource = (url, options = {})=>{
3939
3957
  },
3940
3958
  onclose () {
3941
3959
  if (!explicitlyClosed.current) {
3942
- setStatus("DISCONNECTED");
3960
+ setStatus('DISCONNECTED');
3943
3961
  options.onClose == null ? void 0 : options.onClose.call(options);
3944
3962
  }
3945
3963
  }
@@ -3947,9 +3965,9 @@ const useFetchEventSource = (url, options = {})=>{
3947
3965
  } catch (err) {
3948
3966
  // 只处理非主动关闭导致的错误
3949
3967
  if (!explicitlyClosed.current) {
3950
- console.error("EventSource Error:", err);
3968
+ console.error('EventSource Error:', err);
3951
3969
  setError(err);
3952
- setStatus("DISCONNECTED");
3970
+ setStatus('DISCONNECTED');
3953
3971
  }
3954
3972
  }
3955
3973
  }));
package/dist/index.d.cts CHANGED
@@ -1996,7 +1996,7 @@ declare const usePreferredContrast: UsePreferredContrast;
1996
1996
 
1997
1997
  declare function usePreferredDark(defaultState?: boolean): boolean;
1998
1998
 
1999
- declare function usePrevious<T>(state: T): T | undefined;
1999
+ declare function usePrevious<T>(value: T): T | undefined;
2000
2000
 
2001
2001
  /**
2002
2002
  * @title useRafFn
@@ -2435,7 +2435,7 @@ interface UseTimeoutOptions {
2435
2435
  /**
2436
2436
  * @en Start the timer immediate after calling this function
2437
2437
  * @zh 立即设置定时器
2438
- * @defaultValue false
2438
+ * @defaultValue true
2439
2439
  */
2440
2440
  immediate?: boolean;
2441
2441
  }
@@ -2476,7 +2476,7 @@ interface UseTimeoutFnOptions {
2476
2476
  /**
2477
2477
  * @en Start the timer immediate after calling this function
2478
2478
  * @zh 立即设置定时器
2479
- * @defaultValue false
2479
+ * @defaultValue true
2480
2480
  */
2481
2481
  immediate?: boolean;
2482
2482
  }
package/dist/index.d.mts CHANGED
@@ -1996,7 +1996,7 @@ declare const usePreferredContrast: UsePreferredContrast;
1996
1996
 
1997
1997
  declare function usePreferredDark(defaultState?: boolean): boolean;
1998
1998
 
1999
- declare function usePrevious<T>(state: T): T | undefined;
1999
+ declare function usePrevious<T>(value: T): T | undefined;
2000
2000
 
2001
2001
  /**
2002
2002
  * @title useRafFn
@@ -2435,7 +2435,7 @@ interface UseTimeoutOptions {
2435
2435
  /**
2436
2436
  * @en Start the timer immediate after calling this function
2437
2437
  * @zh 立即设置定时器
2438
- * @defaultValue false
2438
+ * @defaultValue true
2439
2439
  */
2440
2440
  immediate?: boolean;
2441
2441
  }
@@ -2476,7 +2476,7 @@ interface UseTimeoutFnOptions {
2476
2476
  /**
2477
2477
  * @en Start the timer immediate after calling this function
2478
2478
  * @zh 立即设置定时器
2479
- * @defaultValue false
2479
+ * @defaultValue true
2480
2480
  */
2481
2481
  immediate?: boolean;
2482
2482
  }
package/dist/index.d.ts CHANGED
@@ -1996,7 +1996,7 @@ declare const usePreferredContrast: UsePreferredContrast;
1996
1996
 
1997
1997
  declare function usePreferredDark(defaultState?: boolean): boolean;
1998
1998
 
1999
- declare function usePrevious<T>(state: T): T | undefined;
1999
+ declare function usePrevious<T>(value: T): T | undefined;
2000
2000
 
2001
2001
  /**
2002
2002
  * @title useRafFn
@@ -2435,7 +2435,7 @@ interface UseTimeoutOptions {
2435
2435
  /**
2436
2436
  * @en Start the timer immediate after calling this function
2437
2437
  * @zh 立即设置定时器
2438
- * @defaultValue false
2438
+ * @defaultValue true
2439
2439
  */
2440
2440
  immediate?: boolean;
2441
2441
  }
@@ -2476,7 +2476,7 @@ interface UseTimeoutFnOptions {
2476
2476
  /**
2477
2477
  * @en Start the timer immediate after calling this function
2478
2478
  * @zh 立即设置定时器
2479
- * @defaultValue false
2479
+ * @defaultValue true
2480
2480
  */
2481
2481
  immediate?: boolean;
2482
2482
  }
package/dist/index.mjs CHANGED
@@ -1,16 +1,10 @@
1
- import React, { useRef, useEffect, useState, useCallback, useLayoutEffect, useMemo, useReducer } from 'react';
1
+ import React, { useLayoutEffect, useEffect, useRef, useReducer, useState, useCallback, useMemo } from 'react';
2
2
  import { isEqual, debounce, throttle } from 'lodash-es';
3
3
  import Cookies from 'js-cookie';
4
4
  import screenfull from 'screenfull';
5
5
  import { useSyncExternalStore } from 'use-sync-external-store/shim/index.js';
6
6
  import { fetchEventSource } from '@microsoft/fetch-event-source';
7
7
 
8
- const useLatest = (value)=>{
9
- const ref = useRef(value);
10
- ref.current = value;
11
- return ref;
12
- };
13
-
14
8
  var _window_navigator, _window;
15
9
  function isFunction(val) {
16
10
  return typeof val === 'function';
@@ -24,6 +18,18 @@ const isNavigator = typeof navigator !== 'undefined';
24
18
  function noop() {}
25
19
  const isIOS = isBrowser && ((_window = window) == null ? void 0 : (_window_navigator = _window.navigator) == null ? void 0 : _window_navigator.userAgent) && /iP(?:ad|hone|od)/.test(window.navigator.userAgent);
26
20
 
21
+ const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;
22
+
23
+ const useLatest = (value)=>{
24
+ const ref = useRef(value);
25
+ useIsomorphicLayoutEffect(()=>{
26
+ ref.current = value;
27
+ }, [
28
+ value
29
+ ]);
30
+ return ref;
31
+ };
32
+
27
33
  function on(obj, ...args) {
28
34
  if (obj && obj.addEventListener) {
29
35
  obj.addEventListener(...args);
@@ -35,6 +41,7 @@ function off(obj, ...args) {
35
41
  }
36
42
  }
37
43
  const defaultWindow = isBrowser ? window : undefined;
44
+ const defaultDocument = isBrowser ? document : undefined;
38
45
 
39
46
  const defaultOptions$1 = {};
40
47
  function defaultOnError(e) {
@@ -59,6 +66,12 @@ function getTargetElement(target, defaultElement) {
59
66
  return targetElement;
60
67
  }
61
68
 
69
+ const updateReducer = (num)=>(num + 1) % 1000000;
70
+ function useUpdate() {
71
+ const [, update] = useReducer(updateReducer, 0);
72
+ return update;
73
+ }
74
+
62
75
  const useCustomCompareEffect = (effect, deps, depsEqual)=>{
63
76
  if (process.env.NODE_ENV !== 'production') {
64
77
  if (!Array.isArray(deps) || !deps.length) {
@@ -69,9 +82,16 @@ const useCustomCompareEffect = (effect, deps, depsEqual)=>{
69
82
  }
70
83
  }
71
84
  const ref = useRef(undefined);
72
- if (!ref.current || !depsEqual(deps, ref.current)) {
85
+ const forceUpdate = useUpdate();
86
+ if (!ref.current) {
73
87
  ref.current = deps;
74
88
  }
89
+ useIsomorphicLayoutEffect(()=>{
90
+ if (!depsEqual(deps, ref.current)) {
91
+ ref.current = deps;
92
+ forceUpdate();
93
+ }
94
+ });
75
95
  // eslint-disable-next-line react-hooks/exhaustive-deps
76
96
  useEffect(effect, ref.current);
77
97
  };
@@ -125,8 +145,8 @@ const useActiveElement = ()=>{
125
145
  var _window;
126
146
  setActive((_window = window) == null ? void 0 : _window.document.activeElement);
127
147
  }, []);
128
- useEventListener('blur', listener, ()=>window, true);
129
- useEventListener('focus', listener, ()=>window, true);
148
+ useEventListener('blur', listener, defaultWindow, true);
149
+ useEventListener('focus', listener, defaultWindow, true);
130
150
  useMount(()=>{
131
151
  var _window;
132
152
  setActive((_window = window) == null ? void 0 : _window.document.activeElement);
@@ -280,8 +300,6 @@ const useCookie = (key, options = defaultOptions$1, defaultValue)=>{
280
300
  ];
281
301
  };
282
302
 
283
- const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;
284
-
285
303
  /**
286
304
  * keep function reference immutable
287
305
  */ const useEvent = (fn)=>{
@@ -687,11 +705,11 @@ function useStorage(key, defaultValue, getStorage = ()=>isBrowser ? sessionStora
687
705
  ];
688
706
  }
689
707
 
708
+ function value() {
709
+ return window.matchMedia('(prefers-color-scheme: dark)').matches;
710
+ }
690
711
  const useDarkMode = (options)=>{
691
712
  const { selector = 'html', attribute = 'class', classNameDark = '', classNameLight = '', storageKey = 'reactuses-color-scheme', storage = ()=>isBrowser ? localStorage : undefined, defaultValue = false } = options;
692
- const value = ()=>{
693
- return window.matchMedia('(prefers-color-scheme: dark)').matches;
694
- };
695
713
  const [dark, setDark] = useStorage(storageKey, defaultValue, storage, {
696
714
  mountStorageValue: value
697
715
  });
@@ -2160,7 +2178,7 @@ const useMouse = (target)=>{
2160
2178
  newState.elementH = height;
2161
2179
  }
2162
2180
  setState(newState);
2163
- }, ()=>document);
2181
+ }, defaultDocument);
2164
2182
  return state;
2165
2183
  };
2166
2184
 
@@ -2457,24 +2475,24 @@ function usePreferredDark(defaultState) {
2457
2475
  return useMediaQuery('(prefers-color-scheme: dark)', defaultState);
2458
2476
  }
2459
2477
 
2460
- function usePrevious(state) {
2461
- const ref = useRef();
2462
- useEffect(()=>{
2463
- ref.current = state;
2464
- });
2465
- return ref.current;
2478
+ // Following these issues I think this is the best way to implement usePrevious:
2479
+ // https://github.com/childrentime/reactuse/issues/115
2480
+ // https://github.com/streamich/react-use/issues/2605
2481
+ // https://github.com/alibaba/hooks/issues/2162
2482
+ function usePrevious(value) {
2483
+ const [current, setCurrent] = useState(value);
2484
+ const [previous, setPrevious] = useState();
2485
+ if (value !== current) {
2486
+ setPrevious(current);
2487
+ setCurrent(value);
2488
+ }
2489
+ return previous;
2466
2490
  }
2467
2491
 
2468
2492
  function useReducedMotion(defaultState) {
2469
2493
  return useMediaQuery('(prefers-reduced-motion: reduce)', defaultState);
2470
2494
  }
2471
2495
 
2472
- const updateReducer = (num)=>(num + 1) % 1000000;
2473
- function useUpdate() {
2474
- const [, update] = useReducer(updateReducer, 0);
2475
- return update;
2476
- }
2477
-
2478
2496
  const topVarName = '--reactuse-safe-area-top';
2479
2497
  const rightVarName = '--reactuse-safe-area-right';
2480
2498
  const bottomVarName = '--reactuse-safe-area-bottom';
@@ -3836,7 +3854,7 @@ function _object_without_properties_loose(source, excluded) {
3836
3854
  const useFetchEventSource = (url, options = {})=>{
3837
3855
  const [data, setData] = useState(null);
3838
3856
  const [error, setError] = useState(null);
3839
- const [status, setStatus] = useState("DISCONNECTED");
3857
+ const [status, setStatus] = useState('DISCONNECTED');
3840
3858
  const [event, setEvent] = useState(null);
3841
3859
  const [lastEventId, setLastEventId] = useState(null);
3842
3860
  const retries = useRef(0);
@@ -3848,13 +3866,13 @@ const useFetchEventSource = (url, options = {})=>{
3848
3866
  explicitlyClosed.current = true;
3849
3867
  (_abortController_current = abortController.current) == null ? void 0 : _abortController_current.abort();
3850
3868
  abortController.current = null;
3851
- setStatus("DISCONNECTED");
3869
+ setStatus('DISCONNECTED');
3852
3870
  options.onClose == null ? void 0 : options.onClose.call(options);
3853
3871
  }
3854
3872
  });
3855
3873
  const open = useEvent(/*#__PURE__*/ _async_to_generator(function*() {
3856
3874
  close();
3857
- setStatus("CONNECTING");
3875
+ setStatus('CONNECTING');
3858
3876
  explicitlyClosed.current = false;
3859
3877
  retries.current = 0;
3860
3878
  // 创建新的 AbortController
@@ -3873,20 +3891,20 @@ const useFetchEventSource = (url, options = {})=>{
3873
3891
  ]);
3874
3892
  // 构建请求配置
3875
3893
  const finalOptions = _extends({
3876
- method: options.method || "GET",
3894
+ method: options.method || 'GET',
3877
3895
  headers: _extends({
3878
- Accept: "text/event-stream",
3879
- "Cache-Control": "no-cache",
3880
- Connection: "keep-alive"
3896
+ 'Accept': 'text/event-stream',
3897
+ 'Cache-Control': 'no-cache',
3898
+ 'Connection': 'keep-alive'
3881
3899
  }, options.headers),
3882
3900
  signal: abortController.current.signal,
3883
- credentials: withCredentials ? "include" : "same-origin"
3901
+ credentials: withCredentials ? 'include' : 'same-origin'
3884
3902
  }, fetchOptions);
3885
3903
  // 只在 POST 请求时添加 body
3886
- if (options.method === "POST" && body) {
3904
+ if (options.method === 'POST' && body) {
3887
3905
  finalOptions.body = body;
3888
3906
  finalOptions.headers = _extends({}, finalOptions.headers, {
3889
- "Content-Type": "application/json"
3907
+ 'Content-Type': 'application/json'
3890
3908
  });
3891
3909
  }
3892
3910
  yield fetchEventSource(url.toString(), _extends({}, finalOptions, {
@@ -3894,7 +3912,7 @@ const useFetchEventSource = (url, options = {})=>{
3894
3912
  onopen (response) {
3895
3913
  return _async_to_generator(function*() {
3896
3914
  if (response.ok) {
3897
- setStatus("CONNECTED");
3915
+ setStatus('CONNECTED');
3898
3916
  setError(null);
3899
3917
  options.onOpen == null ? void 0 : options.onOpen.call(options);
3900
3918
  } else {
@@ -3915,12 +3933,12 @@ const useFetchEventSource = (url, options = {})=>{
3915
3933
  },
3916
3934
  onerror (err) {
3917
3935
  setError(err);
3918
- setStatus("DISCONNECTED");
3936
+ setStatus('DISCONNECTED');
3919
3937
  const retryDelay = options.onError == null ? void 0 : options.onError.call(options, err);
3920
3938
  if (options.autoReconnect && !explicitlyClosed.current) {
3921
3939
  const { retries: maxRetries = -1, delay = 1000, onFailed } = options.autoReconnect;
3922
3940
  retries.current += 1;
3923
- if (typeof maxRetries === "number" && (maxRetries < 0 || retries.current < maxRetries) || typeof maxRetries === "function" && maxRetries()) {
3941
+ if (typeof maxRetries === 'number' && (maxRetries < 0 || retries.current < maxRetries) || typeof maxRetries === 'function' && maxRetries()) {
3924
3942
  return retryDelay != null ? retryDelay : delay;
3925
3943
  } else {
3926
3944
  onFailed == null ? void 0 : onFailed();
@@ -3931,7 +3949,7 @@ const useFetchEventSource = (url, options = {})=>{
3931
3949
  },
3932
3950
  onclose () {
3933
3951
  if (!explicitlyClosed.current) {
3934
- setStatus("DISCONNECTED");
3952
+ setStatus('DISCONNECTED');
3935
3953
  options.onClose == null ? void 0 : options.onClose.call(options);
3936
3954
  }
3937
3955
  }
@@ -3939,9 +3957,9 @@ const useFetchEventSource = (url, options = {})=>{
3939
3957
  } catch (err) {
3940
3958
  // 只处理非主动关闭导致的错误
3941
3959
  if (!explicitlyClosed.current) {
3942
- console.error("EventSource Error:", err);
3960
+ console.error('EventSource Error:', err);
3943
3961
  setError(err);
3944
- setStatus("DISCONNECTED");
3962
+ setStatus('DISCONNECTED');
3945
3963
  }
3946
3964
  }
3947
3965
  }));
@@ -1,13 +1,24 @@
1
1
  Object.defineProperty(exports, '__esModule', { value: true });
2
2
 
3
3
  var QRCode = require('qrcode');
4
- var react = require('react');
4
+ var React = require('react');
5
5
  var lodashEs = require('lodash-es');
6
6
 
7
7
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
8
 
9
9
  var QRCode__default = /*#__PURE__*/_interopDefault(QRCode);
10
10
 
11
+ process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test';
12
+ const isBrowser = typeof window !== 'undefined';
13
+
14
+ const useIsomorphicLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect;
15
+
16
+ const updateReducer = (num)=>(num + 1) % 1000000;
17
+ function useUpdate() {
18
+ const [, update] = React.useReducer(updateReducer, 0);
19
+ return update;
20
+ }
21
+
11
22
  const useCustomCompareEffect = (effect, deps, depsEqual)=>{
12
23
  if (process.env.NODE_ENV !== 'production') {
13
24
  if (!Array.isArray(deps) || !deps.length) {
@@ -17,12 +28,19 @@ const useCustomCompareEffect = (effect, deps, depsEqual)=>{
17
28
  console.warn('`useCustomCompareEffect` should be used with depsEqual callback for comparing deps list');
18
29
  }
19
30
  }
20
- const ref = react.useRef(undefined);
21
- if (!ref.current || !depsEqual(deps, ref.current)) {
31
+ const ref = React.useRef(undefined);
32
+ const forceUpdate = useUpdate();
33
+ if (!ref.current) {
22
34
  ref.current = deps;
23
35
  }
36
+ useIsomorphicLayoutEffect(()=>{
37
+ if (!depsEqual(deps, ref.current)) {
38
+ ref.current = deps;
39
+ forceUpdate();
40
+ }
41
+ });
24
42
  // eslint-disable-next-line react-hooks/exhaustive-deps
25
- react.useEffect(effect, ref.current);
43
+ React.useEffect(effect, ref.current);
26
44
  };
27
45
 
28
46
  const useDeepCompareEffect = (effect, deps)=>{
@@ -69,8 +87,8 @@ function generateQRCode(text, options) {
69
87
  return QRCode__default.default.toDataURL(text, options);
70
88
  }
71
89
  const useQRCode = (text, options = defaultOptions)=>{
72
- const [qrCode, setQRCode] = react.useState('');
73
- const [error, setError] = react.useState(null);
90
+ const [qrCode, setQRCode] = React.useState('');
91
+ const [error, setError] = React.useState(null);
74
92
  useDeepCompareEffect(()=>{
75
93
  const generate = /*#__PURE__*/ _async_to_generator(function*() {
76
94
  try {
@@ -1,7 +1,18 @@
1
1
  import QRCode from 'qrcode';
2
- import { useRef, useEffect, useState } from 'react';
2
+ import { useLayoutEffect, useEffect, useReducer, useRef, useState } from 'react';
3
3
  import { isEqual } from 'lodash-es';
4
4
 
5
+ process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test';
6
+ const isBrowser = typeof window !== 'undefined';
7
+
8
+ const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;
9
+
10
+ const updateReducer = (num)=>(num + 1) % 1000000;
11
+ function useUpdate() {
12
+ const [, update] = useReducer(updateReducer, 0);
13
+ return update;
14
+ }
15
+
5
16
  const useCustomCompareEffect = (effect, deps, depsEqual)=>{
6
17
  if (process.env.NODE_ENV !== 'production') {
7
18
  if (!Array.isArray(deps) || !deps.length) {
@@ -12,9 +23,16 @@ const useCustomCompareEffect = (effect, deps, depsEqual)=>{
12
23
  }
13
24
  }
14
25
  const ref = useRef(undefined);
15
- if (!ref.current || !depsEqual(deps, ref.current)) {
26
+ const forceUpdate = useUpdate();
27
+ if (!ref.current) {
16
28
  ref.current = deps;
17
29
  }
30
+ useIsomorphicLayoutEffect(()=>{
31
+ if (!depsEqual(deps, ref.current)) {
32
+ ref.current = deps;
33
+ forceUpdate();
34
+ }
35
+ });
18
36
  // eslint-disable-next-line react-hooks/exhaustive-deps
19
37
  useEffect(effect, ref.current);
20
38
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactuses/core",
3
- "version": "5.0.23-beta.1",
3
+ "version": "6.0.0",
4
4
  "license": "Unlicense",
5
5
  "homepage": "https://www.reactuse.com/",
6
6
  "repository": {
@@ -66,7 +66,7 @@
66
66
  },
67
67
  "peerDependencies": {
68
68
  "qrcode": "^1.5",
69
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
69
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
70
70
  },
71
71
  "peerDependenciesMeta": {
72
72
  "qrcode": {
@@ -99,8 +99,8 @@
99
99
  "jest-environment-node": "^29.7.0",
100
100
  "lodash": "^4.17.21",
101
101
  "qrcode": "^1.5.3",
102
- "react": "^18.2.0",
103
- "react-dom": "^18.2.0",
102
+ "react": "^19.0.0",
103
+ "react-dom": "^19.0.0",
104
104
  "typescript": "^5.3.3"
105
105
  }
106
106
  }