@dynamic-labs/sdk-react-core 2.5.3 → 2.6.1
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/CHANGELOG.md +9 -0
- package/package.cjs +2 -2
- package/package.js +2 -2
- package/package.json +14 -14
- package/src/lib/components/QRCode/QRCode.d.ts +15 -0
- package/src/lib/components/UserProfile/parts/UserProfileSocialAccount/UserProfileSocialAccount.cjs +1 -1
- package/src/lib/components/UserProfile/parts/UserProfileSocialAccount/UserProfileSocialAccount.js +1 -1
- package/src/lib/config/ApiEndpoint.cjs +6 -20
- package/src/lib/config/ApiEndpoint.d.ts +1 -2
- package/src/lib/config/ApiEndpoint.js +6 -20
- package/src/lib/context/DynamicContext/DynamicContext.cjs +2 -0
- package/src/lib/context/DynamicContext/DynamicContext.d.ts +2 -0
- package/src/lib/context/DynamicContext/DynamicContext.js +2 -0
- package/src/lib/context/DynamicContext/types/SocialSettings.d.ts +7 -0
- package/src/lib/context/DynamicContext/types/index.d.ts +2 -0
- package/src/lib/context/SocialRedirectContext/SocialRedirectContext.cjs +4 -0
- package/src/lib/context/SocialRedirectContext/SocialRedirectContext.js +4 -0
- package/src/lib/context/SocialRedirectContext/hooks/useRedirectSocialHandler/index.d.ts +1 -0
- package/src/lib/context/SocialRedirectContext/hooks/useRedirectSocialHandler/useRedirectSocialHandler.cjs +150 -0
- package/src/lib/context/SocialRedirectContext/hooks/useRedirectSocialHandler/useRedirectSocialHandler.d.ts +7 -0
- package/src/lib/context/SocialRedirectContext/hooks/useRedirectSocialHandler/useRedirectSocialHandler.js +146 -0
- package/src/lib/data/api/embeddedWallets/embeddedWallets.cjs +1 -1
- package/src/lib/data/api/embeddedWallets/embeddedWallets.js +1 -1
- package/src/lib/data/api/oauth/oauth.cjs +13 -0
- package/src/lib/data/api/oauth/oauth.d.ts +2 -1
- package/src/lib/data/api/oauth/oauth.js +13 -1
- package/src/lib/shared/utils/hooks/index.d.ts +1 -0
- package/src/lib/shared/utils/hooks/useEffectOnceCondition/index.d.ts +1 -0
- package/src/lib/shared/utils/hooks/useEffectOnceCondition/useEffectOnceCondition.cjs +26 -0
- package/src/lib/shared/utils/hooks/useEffectOnceCondition/useEffectOnceCondition.d.ts +7 -0
- package/src/lib/shared/utils/hooks/useEffectOnceCondition/useEffectOnceCondition.js +22 -0
- package/src/lib/styles/index.shadow.cjs +1 -1
- package/src/lib/styles/index.shadow.js +1 -1
- package/src/lib/utils/functions/index.d.ts +1 -0
- package/src/lib/utils/functions/socialStorage/index.d.ts +1 -0
- package/src/lib/utils/functions/socialStorage/socialStorage.cjs +36 -0
- package/src/lib/utils/functions/socialStorage/socialStorage.d.ts +17 -0
- package/src/lib/utils/functions/socialStorage/socialStorage.js +29 -0
- package/src/lib/utils/hooks/useSocialAuth/apple/connectWithAppleId.cjs +26 -0
- package/src/lib/utils/hooks/useSocialAuth/apple/connectWithAppleId.d.ts +7 -0
- package/src/lib/utils/hooks/useSocialAuth/apple/connectWithAppleId.js +22 -0
- package/src/lib/utils/hooks/useSocialAuth/apple/loadAppleId.cjs +34 -0
- package/src/lib/utils/hooks/useSocialAuth/apple/loadAppleId.d.ts +1 -0
- package/src/lib/utils/hooks/useSocialAuth/apple/loadAppleId.js +30 -0
- package/src/lib/utils/hooks/useSocialAuth/index.d.ts +1 -1
- package/src/lib/utils/hooks/useSocialAuth/useSocialAuth.cjs +85 -27
- package/src/lib/utils/hooks/useSocialAuth/useSocialAuth.d.ts +9 -1
- package/src/lib/utils/hooks/useSocialAuth/useSocialAuth.js +90 -32
- package/src/lib/widgets/DynamicEmbeddedWidget/DynamicEmbeddedAuthFlow/DynamicEmbeddedAuthFlow.cjs +1 -2
- package/src/lib/widgets/DynamicEmbeddedWidget/DynamicEmbeddedAuthFlow/DynamicEmbeddedAuthFlow.js +1 -2
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../../../../../_virtual/_tslib.js';
|
|
3
|
+
import { useState, useCallback } from 'react';
|
|
4
|
+
import '@dynamic-labs/sdk-api-core';
|
|
5
|
+
import '../../../../shared/logger.js';
|
|
6
|
+
import '@dynamic-labs/iconic';
|
|
7
|
+
import '@dynamic-labs/wallet-connector-core';
|
|
8
|
+
import 'react/jsx-runtime';
|
|
9
|
+
import { useViewContext } from '../../../ViewContext/ViewContext.js';
|
|
10
|
+
import '@dynamic-labs/wallet-book';
|
|
11
|
+
import { isSSR } from '../../../../shared/utils/functions/isSSR/isSSR.js';
|
|
12
|
+
import '../../../../utils/constants/colors.js';
|
|
13
|
+
import '../../../../utils/constants/values.js';
|
|
14
|
+
import '../../../../shared/utils/classes/storage/localStorage.js';
|
|
15
|
+
import { useEffectOnce } from '../../../../shared/utils/hooks/useEffectOnce/useEffectOnce.js';
|
|
16
|
+
import '@dynamic-labs/logger';
|
|
17
|
+
import '@dynamic-labs/utils';
|
|
18
|
+
import { useEffectOnceCondition } from '../../../../shared/utils/hooks/useEffectOnceCondition/useEffectOnceCondition.js';
|
|
19
|
+
import '../../../../shared/consts/index.js';
|
|
20
|
+
import '../../../DynamicContext/DynamicContext.js';
|
|
21
|
+
import '../../../../events/dynamicEvents.js';
|
|
22
|
+
import '../../../CaptchaContext/CaptchaContext.js';
|
|
23
|
+
import '../../../ErrorContext/ErrorContext.js';
|
|
24
|
+
import '@dynamic-labs/multi-wallet';
|
|
25
|
+
import 'react-international-phone';
|
|
26
|
+
import { getSocialSignInProviderForProviderEnum } from '../../../../utils/functions/getSocialSignInProviderForProviderEnum/getSocialSignInProviderForProviderEnum.js';
|
|
27
|
+
import 'viem';
|
|
28
|
+
import 'viem/chains';
|
|
29
|
+
import '../../../../config/ApiEndpoint.js';
|
|
30
|
+
import '@dynamic-labs/store';
|
|
31
|
+
import '../../../../locale/locale.js';
|
|
32
|
+
import { searchSocialStorageByState, deleteSocialStorage } from '../../../../utils/functions/socialStorage/socialStorage.js';
|
|
33
|
+
import '../../../AccessDeniedContext/AccessDeniedContext.js';
|
|
34
|
+
import '../../../AccountExistsContext/AccountExistsContext.js';
|
|
35
|
+
import '../../../UserWalletsContext/UserWalletsContext.js';
|
|
36
|
+
import '../../../VerificationContext/VerificationContext.js';
|
|
37
|
+
import 'react-dom';
|
|
38
|
+
import '../../../WalletContext/WalletContext.js';
|
|
39
|
+
import '../../../ThemeContext/ThemeContext.js';
|
|
40
|
+
import '../../../../utils/hooks/useUserUpdateRequest/useUpdateUser/userFieldsSchema.js';
|
|
41
|
+
import '@dynamic-labs/types';
|
|
42
|
+
import { useSocialAuth } from '../../../../utils/hooks/useSocialAuth/useSocialAuth.js';
|
|
43
|
+
import 'yup';
|
|
44
|
+
import '../../../MockContext/MockContext.js';
|
|
45
|
+
import '../../../../views/CollectUserDataView/useFields.js';
|
|
46
|
+
import '../../../FieldsStateContext/FieldsStateContext.js';
|
|
47
|
+
import '../../../UserFieldEditorContext/UserFieldEditorContext.js';
|
|
48
|
+
import '@dynamic-labs/rpc-providers';
|
|
49
|
+
import 'react-i18next';
|
|
50
|
+
import '../../../../components/Accordion/components/AccordionItem/AccordionItem.js';
|
|
51
|
+
import '../../../../components/Alert/Alert.js';
|
|
52
|
+
import '../../../../components/ShadowDOM/ShadowDOM.js';
|
|
53
|
+
import '../../../../components/IconButton/IconButton.js';
|
|
54
|
+
import '../../../../components/InlineWidget/InlineWidget.js';
|
|
55
|
+
import '../../../../components/Input/Input.js';
|
|
56
|
+
import '../../../../components/IsBrowser/IsBrowser.js';
|
|
57
|
+
import '../../../../components/MenuList/Dropdown/Dropdown.js';
|
|
58
|
+
import '../../../../components/Transition/ZoomTransition/ZoomTransition.js';
|
|
59
|
+
import '../../../../components/Transition/SlideInUpTransition/SlideInUpTransition.js';
|
|
60
|
+
import '../../../../components/Transition/OpacityTransition/OpacityTransition.js';
|
|
61
|
+
import '../../../../components/OverlayCard/OverlayCardTarget/OverlayCardTarget.js';
|
|
62
|
+
import '../../../../components/PasskeyCreatedSuccessBanner/PasskeyCreatedSuccessBanner.js';
|
|
63
|
+
import '../../../../components/Popper/Popper/Popper.js';
|
|
64
|
+
import '../../../../components/Popper/PopperContext/PopperContext.js';
|
|
65
|
+
import 'react-focus-lock';
|
|
66
|
+
import 'qrcode';
|
|
67
|
+
import 'formik';
|
|
68
|
+
import '../../../../views/WalletList/WalletList.js';
|
|
69
|
+
import '../../SocialRedirectContext.js';
|
|
70
|
+
import '../../../../widgets/DynamicBridgeWidget/views/WalletsView/components/SecondaryWallets/SecondaryWallets.js';
|
|
71
|
+
import '@hcaptcha/react-hcaptcha';
|
|
72
|
+
import '../../../LoadingContext/LoadingContext.js';
|
|
73
|
+
import { useWidgetContext } from '../../../../widgets/DynamicWidget/context/DynamicWidgetContext.js';
|
|
74
|
+
import '../../../FooterAnimationContext/index.js';
|
|
75
|
+
import '../../../WalletGroupContext/WalletGroupContext.js';
|
|
76
|
+
import '../../../MfaSettingsContext/MfaSettingsContext.js';
|
|
77
|
+
import '../../../IpConfigurationContext/IpConfigurationContext.js';
|
|
78
|
+
import '../../../PasskeyContext/PasskeyContext.js';
|
|
79
|
+
import '../../../../widgets/DynamicWidget/components/DynamicWidgetHeader/DynamicWidgetHeader.js';
|
|
80
|
+
import '../../../../views/TransactionConfirmationView/helpers/transactionErrorMessage.js';
|
|
81
|
+
import '../../../../widgets/DynamicWidget/views/ManagePasskeysWidgetView/PasskeyCard/PasskeyCard.js';
|
|
82
|
+
import { useInternalDynamicContext } from '../../../DynamicContext/useDynamicContext/useInternalDynamicContext.js';
|
|
83
|
+
|
|
84
|
+
const useRedirectSocialHandler = ({ setSocialProvider, }) => {
|
|
85
|
+
const { setView } = useViewContext();
|
|
86
|
+
const { setDynamicWidgetView } = useWidgetContext();
|
|
87
|
+
const [socialStorageItem, setSocialStorageItem] = useState(null);
|
|
88
|
+
const { sdkHasLoaded, user, setShowAuthFlow, isRenderingEmbeddedAuthFlow, setShowDynamicUserProfile, } = useInternalDynamicContext();
|
|
89
|
+
const { completeConnection } = useSocialAuth({
|
|
90
|
+
sessionTimeout: 10000,
|
|
91
|
+
});
|
|
92
|
+
const updateInterfaceStateForSignIn = useCallback((socialStorageItem) => {
|
|
93
|
+
const socialSignInProvider = getSocialSignInProviderForProviderEnum(socialStorageItem.provider);
|
|
94
|
+
setSocialProvider(socialSignInProvider);
|
|
95
|
+
setView('social-redirect-view');
|
|
96
|
+
// Only open the auth flow when the embedded widget is not rendered
|
|
97
|
+
if (!isRenderingEmbeddedAuthFlow.current) {
|
|
98
|
+
setShowAuthFlow(true);
|
|
99
|
+
}
|
|
100
|
+
}, [setSocialProvider, setView, isRenderingEmbeddedAuthFlow, setShowAuthFlow]);
|
|
101
|
+
const updateInterfaceStateForLink = useCallback(() => {
|
|
102
|
+
setDynamicWidgetView('profile');
|
|
103
|
+
setShowDynamicUserProfile(true);
|
|
104
|
+
}, [setDynamicWidgetView, setShowDynamicUserProfile]);
|
|
105
|
+
useEffectOnce(() => {
|
|
106
|
+
// Do not run on server side
|
|
107
|
+
if (isSSR())
|
|
108
|
+
return;
|
|
109
|
+
const url = new URL(window.location.href);
|
|
110
|
+
const dynamicOauthState = url.searchParams.get('dynamicOauthState');
|
|
111
|
+
const dynamicOauthCode = url.searchParams.get('dynamicOauthCode');
|
|
112
|
+
if (!dynamicOauthState || !dynamicOauthCode) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const socialStorageItem = searchSocialStorageByState(dynamicOauthState);
|
|
116
|
+
if (!socialStorageItem)
|
|
117
|
+
return;
|
|
118
|
+
// we got back the dynamicOauthCode from the oauth provider, set it here so we can use it to sign in
|
|
119
|
+
socialStorageItem.code = dynamicOauthCode;
|
|
120
|
+
setSocialStorageItem(socialStorageItem);
|
|
121
|
+
// Clear the state from local storage
|
|
122
|
+
deleteSocialStorage(socialStorageItem.provider);
|
|
123
|
+
});
|
|
124
|
+
useEffectOnceCondition(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
125
|
+
if (!socialStorageItem)
|
|
126
|
+
return;
|
|
127
|
+
const authMode = user ? 'link' : 'signin';
|
|
128
|
+
// Update UI to reflect the original state
|
|
129
|
+
if (authMode === 'signin') {
|
|
130
|
+
updateInterfaceStateForSignIn(socialStorageItem);
|
|
131
|
+
}
|
|
132
|
+
else if (authMode === 'link') {
|
|
133
|
+
updateInterfaceStateForLink();
|
|
134
|
+
}
|
|
135
|
+
yield completeConnection({
|
|
136
|
+
authCode: socialStorageItem.code,
|
|
137
|
+
authMode,
|
|
138
|
+
captchaToken: socialStorageItem.captchaToken,
|
|
139
|
+
provider: socialStorageItem.provider,
|
|
140
|
+
state: socialStorageItem.state,
|
|
141
|
+
verifier: socialStorageItem.codeVerifier,
|
|
142
|
+
});
|
|
143
|
+
}), Boolean(socialStorageItem) && sdkHasLoaded);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export { useRedirectSocialHandler };
|
|
@@ -24,7 +24,7 @@ var storeAuthTokenAndUser = require('../../../store/utils/storeAuthTokenAndUser/
|
|
|
24
24
|
const createTurnkeyEmbeddedWallet = (_a) => _tslib.__awaiter(void 0, [_a], void 0, function* ({ attestation, challenge, environmentId, chains = [sdkApiCore.ChainEnum.Evm], passkeyAlias, }) {
|
|
25
25
|
const embeddedWallets = [
|
|
26
26
|
{
|
|
27
|
-
chains,
|
|
27
|
+
chains: chains,
|
|
28
28
|
embeddedWalletProvider: sdkApiCore.EmbeddedWalletProviderEnum.Turnkeyhd,
|
|
29
29
|
isAuthenticatorAttached: false,
|
|
30
30
|
passkeyAlias,
|
|
@@ -20,7 +20,7 @@ import { storeAuthTokenAndUser } from '../../../store/utils/storeAuthTokenAndUse
|
|
|
20
20
|
const createTurnkeyEmbeddedWallet = (_a) => __awaiter(void 0, [_a], void 0, function* ({ attestation, challenge, environmentId, chains = [ChainEnum.Evm], passkeyAlias, }) {
|
|
21
21
|
const embeddedWallets = [
|
|
22
22
|
{
|
|
23
|
-
chains,
|
|
23
|
+
chains: chains,
|
|
24
24
|
embeddedWalletProvider: EmbeddedWalletProviderEnum.Turnkeyhd,
|
|
25
25
|
isAuthenticatorAttached: false,
|
|
26
26
|
passkeyAlias,
|
|
@@ -21,6 +21,18 @@ require('../../../shared/consts/index.cjs');
|
|
|
21
21
|
var api = require('../api.cjs');
|
|
22
22
|
var storeAuthTokenAndUser = require('../../../store/utils/storeAuthTokenAndUser/storeAuthTokenAndUser.cjs');
|
|
23
23
|
|
|
24
|
+
const initAuth = (environmentId, providerType, oauthInitAuthRequest) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
25
|
+
try {
|
|
26
|
+
yield api.sdkApi().initAuth({
|
|
27
|
+
environmentId,
|
|
28
|
+
oauthInitAuthRequest,
|
|
29
|
+
providerType,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
logger.logger.error(e);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
24
36
|
const verifyOAuth = (environmentId_1, providerType_1, _a) => _tslib.__awaiter(void 0, [environmentId_1, providerType_1, _a], void 0, function* (environmentId, providerType, { code, codeVerifier, state }) {
|
|
25
37
|
const oauthRequest = {
|
|
26
38
|
code,
|
|
@@ -134,6 +146,7 @@ const farcasterVerify = (farcasterVerifyRequest) => _tslib.__awaiter(void 0, voi
|
|
|
134
146
|
|
|
135
147
|
exports.farcasterSignIn = farcasterSignIn;
|
|
136
148
|
exports.farcasterVerify = farcasterVerify;
|
|
149
|
+
exports.initAuth = initAuth;
|
|
137
150
|
exports.signInOAuth = signInOAuth;
|
|
138
151
|
exports.unlinkOAuth = unlinkOAuth;
|
|
139
152
|
exports.verifyOAuth = verifyOAuth;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { FarcasterSignInRequest, OauthRequest, OauthResultRequest, OauthResultResponse, ProviderEnum, FarcasterVerifyRequest } from '@dynamic-labs/sdk-api-core';
|
|
1
|
+
import { FarcasterSignInRequest, OauthRequest, OauthResultRequest, OauthResultResponse, ProviderEnum, FarcasterVerifyRequest, OauthInitAuthRequest } from '@dynamic-labs/sdk-api-core';
|
|
2
2
|
import { UserProfile } from '../../../..';
|
|
3
3
|
export declare const getOauthLoginUrl: (environmentId: string, providerType: ProviderEnum) => Promise<string | undefined>;
|
|
4
|
+
export declare const initAuth: (environmentId: string, providerType: ProviderEnum, oauthInitAuthRequest: OauthInitAuthRequest) => Promise<void>;
|
|
4
5
|
export declare const verifyOAuth: (environmentId: string, providerType: ProviderEnum, { code, codeVerifier, state }: OauthRequest) => Promise<UserProfile | undefined>;
|
|
5
6
|
export declare const unlinkOAuth: ({ environmentId, primaryWalletId, verifiedCrentialId, }: {
|
|
6
7
|
environmentId: string;
|
|
@@ -17,6 +17,18 @@ import '../../../shared/consts/index.js';
|
|
|
17
17
|
import { sdkApi } from '../api.js';
|
|
18
18
|
import { storeAuthTokenAndUser } from '../../../store/utils/storeAuthTokenAndUser/storeAuthTokenAndUser.js';
|
|
19
19
|
|
|
20
|
+
const initAuth = (environmentId, providerType, oauthInitAuthRequest) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
try {
|
|
22
|
+
yield sdkApi().initAuth({
|
|
23
|
+
environmentId,
|
|
24
|
+
oauthInitAuthRequest,
|
|
25
|
+
providerType,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
logger.error(e);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
20
32
|
const verifyOAuth = (environmentId_1, providerType_1, _a) => __awaiter(void 0, [environmentId_1, providerType_1, _a], void 0, function* (environmentId, providerType, { code, codeVerifier, state }) {
|
|
21
33
|
const oauthRequest = {
|
|
22
34
|
code,
|
|
@@ -128,4 +140,4 @@ const farcasterVerify = (farcasterVerifyRequest) => __awaiter(void 0, void 0, vo
|
|
|
128
140
|
}
|
|
129
141
|
});
|
|
130
142
|
|
|
131
|
-
export { farcasterSignIn, farcasterVerify, signInOAuth, unlinkOAuth, verifyOAuth };
|
|
143
|
+
export { farcasterSignIn, farcasterVerify, initAuth, signInOAuth, unlinkOAuth, verifyOAuth };
|
|
@@ -7,3 +7,4 @@ export { useOnClickOutside } from './useOnClickOutside';
|
|
|
7
7
|
export { usePreventPageScroll } from './usePreventPageScroll';
|
|
8
8
|
export { useThrottle } from './useThrottle';
|
|
9
9
|
export { usePrefetch } from './usePrefetch';
|
|
10
|
+
export { useEffectOnceCondition } from './useEffectOnceCondition';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useEffectOnceCondition } from './useEffectOnceCondition';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var React = require('react');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Hook that runs an effect only once based on a condition.
|
|
10
|
+
*
|
|
11
|
+
* @param {Function} effect - The effect callback function to run.
|
|
12
|
+
* @param {boolean} condition - The condition that determines whether the effect should run.
|
|
13
|
+
*/
|
|
14
|
+
const useEffectOnceCondition = (effect, condition) => {
|
|
15
|
+
const hasRun = React.useRef(false);
|
|
16
|
+
const effectRef = React.useRef(effect);
|
|
17
|
+
effectRef.current = effect;
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
if (condition && !hasRun.current) {
|
|
20
|
+
effectRef.current();
|
|
21
|
+
hasRun.current = true;
|
|
22
|
+
}
|
|
23
|
+
}, [condition]);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
exports.useEffectOnceCondition = useEffectOnceCondition;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook that runs an effect only once based on a condition.
|
|
3
|
+
*
|
|
4
|
+
* @param {Function} effect - The effect callback function to run.
|
|
5
|
+
* @param {boolean} condition - The condition that determines whether the effect should run.
|
|
6
|
+
*/
|
|
7
|
+
export declare const useEffectOnceCondition: (effect: () => void, condition: boolean) => void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { useRef, useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook that runs an effect only once based on a condition.
|
|
6
|
+
*
|
|
7
|
+
* @param {Function} effect - The effect callback function to run.
|
|
8
|
+
* @param {boolean} condition - The condition that determines whether the effect should run.
|
|
9
|
+
*/
|
|
10
|
+
const useEffectOnceCondition = (effect, condition) => {
|
|
11
|
+
const hasRun = useRef(false);
|
|
12
|
+
const effectRef = useRef(effect);
|
|
13
|
+
effectRef.current = effect;
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (condition && !hasRun.current) {
|
|
16
|
+
effectRef.current();
|
|
17
|
+
hasRun.current = true;
|
|
18
|
+
}
|
|
19
|
+
}, [condition]);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export { useEffectOnceCondition };
|