Skip to content

Commit 61a4164

Browse files
chore: added JSDocs to hooks, improved context check
1 parent 43d1579 commit 61a4164

File tree

11 files changed

+234
-41
lines changed

11 files changed

+234
-41
lines changed

packages/appkit/src/AppKitContext.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { createContext, useContext, useMemo, type ReactNode } from 'react';
22
import { AppKit } from './AppKit';
33

4-
interface AppKitContextType {
4+
export interface AppKitContextType {
55
appKit: AppKit | null;
66
}
77

packages/appkit/src/hooks/useAccount.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import {
66
} from '@reown/appkit-core-react-native';
77
import { useMemo } from 'react';
88
import { useSnapshot } from 'valtio';
9-
import { useAppKit } from './useAppKit';
109
import type { AccountType, AppKitNetwork } from '@reown/appkit-common-react-native';
10+
import { useAppKitContext } from './useAppKitContext';
1111

1212
/**
1313
* Represents a blockchain account with its associated metadata
@@ -64,7 +64,7 @@ export interface Account {
6464
* @throws Will log errors via LogController if account parsing fails
6565
*/
6666
export function useAccount() {
67-
useAppKit(); // Use the hook for checks
67+
useAppKitContext();
6868

6969
const {
7070
activeAddress: address,

packages/appkit/src/hooks/useAppKit.ts

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,60 @@
1-
import { useContext, useMemo } from 'react';
1+
import { useMemo } from 'react';
22
import type { ChainNamespace } from '@reown/appkit-common-react-native';
33

44
import type { AppKit } from '../AppKit';
5-
import { AppKitContext } from '../AppKitContext';
5+
import { useAppKitContext } from './useAppKitContext';
66

7+
/**
8+
* Interface representing the return value of the useAppKit hook
9+
*/
710
interface UseAppKitReturn {
11+
/** Function to open the AppKit modal with optional view configuration */
812
open: AppKit['open'];
13+
/** Function to close the AppKit modal */
914
close: AppKit['close'];
15+
/** Function to disconnect the wallet, optionally scoped to a specific namespace */
1016
disconnect: (namespace?: ChainNamespace) => void;
17+
/** Function to switch to a different network */
1118
switchNetwork: AppKit['switchNetwork'];
1219
}
1320

21+
/**
22+
* Hook to access core AppKit functionality for controlling the modal
23+
*
24+
* @remarks
25+
* This hook provides access to the main AppKit instance methods for opening/closing
26+
* the modal, disconnecting wallets, and switching networks. All functions are memoized
27+
* and properly bound to ensure stable references across renders.
28+
*
29+
* @returns {UseAppKitReturn} An object containing:
30+
* - `open`: Opens the AppKit modal, optionally with a specific view
31+
* - `close`: Closes the AppKit modal
32+
* - `disconnect`: Disconnects the current wallet connection (optionally for a specific namespace)
33+
* - `switchNetwork`: Switches to a different blockchain network
34+
*
35+
* @throws {Error} If used outside of an AppKitProvider
36+
* @throws {Error} If AppKit instance is not available in context
37+
*
38+
* @example
39+
* ```tsx
40+
* function MyComponent() {
41+
* const { open, close, disconnect, switchNetwork } = useAppKit();
42+
*
43+
* return (
44+
* <View>
45+
* <Button onPress={() => open()} title="Connect Wallet" />
46+
* <Button onPress={() => disconnect()} title="Disconnect" />
47+
* <Button
48+
* onPress={() => switchNetwork('eip155:1')}
49+
* title="Switch to Ethereum"
50+
* />
51+
* </View>
52+
* );
53+
* }
54+
* ```
55+
*/
1456
export const useAppKit = (): UseAppKitReturn => {
15-
const context = useContext(AppKitContext);
16-
17-
if (context === undefined) {
18-
throw new Error('useAppKit must be used within an AppKitProvider');
19-
}
20-
21-
if (!context.appKit) {
22-
// This might happen if the provider is rendered before AppKit is initialized
23-
throw new Error('AppKit instance is not yet available in context.');
24-
}
57+
const context = useAppKitContext();
2558

2659
const stableFunctions = useMemo(() => {
2760
if (!context.appKit) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { useContext } from 'react';
2+
3+
import { AppKitContext, type AppKitContextType } from '../AppKitContext';
4+
5+
/**
6+
* Hook to access the AppKit context
7+
*
8+
* @remarks
9+
* This is an internal hook used by other AppKit hooks to ensure they're used within
10+
* the AppKitProvider. You typically don't need to use this hook directly - use the
11+
* higher-level hooks like `useAppKit`, `useAccount`, `useAppKitTheme`, etc. instead.
12+
*
13+
* @returns {AppKitContextType} The AppKit context containing the AppKit instance
14+
*
15+
* @throws {Error} If used outside of an AppKitProvider
16+
* @throws {Error} If the AppKit instance is not yet available in context
17+
*
18+
* @internal
19+
*
20+
* @example
21+
* ```tsx
22+
* // This is typically used internally by other hooks
23+
* function MyCustomHook() {
24+
* const context = useAppKitContext();
25+
* // Use context.appKit...
26+
* }
27+
* ```
28+
*/
29+
30+
export const useAppKitContext = (): AppKitContextType => {
31+
const context = useContext(AppKitContext);
32+
33+
if (context === undefined) {
34+
throw new Error('useAppKit must be used within an AppKitProvider');
35+
}
36+
37+
if (!context.appKit) {
38+
// This might happen if the provider is rendered before AppKit is initialized
39+
throw new Error('AppKit instance is not yet available in context.');
40+
}
41+
42+
return context;
43+
};

packages/appkit/src/hooks/useAppKitEvents.ts

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,42 @@ import { useEffect } from 'react';
22
import { useSnapshot } from 'valtio';
33
import { EventsController, type EventsControllerState } from '@reown/appkit-core-react-native';
44
import { type EventName } from '@reown/appkit-common-react-native';
5-
import { useAppKit } from './useAppKit';
5+
import { useAppKitContext } from './useAppKitContext';
66

7+
/**
8+
* Hook to subscribe to all AppKit events
9+
*
10+
* @remarks
11+
* This hook provides reactive access to AppKit's event system, allowing you to
12+
* monitor all events that occur within the AppKit lifecycle (connections, disconnections,
13+
* network changes, etc.). The callback is invoked whenever a new event is emitted.
14+
*
15+
* @param callback - Optional callback function invoked when any event occurs
16+
*
17+
* @returns An object containing:
18+
* - `data`: The most recent event data
19+
* - `timestamp`: The timestamp of the most recent event
20+
*
21+
* @throws {Error} If used outside of an AppKitProvider
22+
*
23+
* @example
24+
* ```tsx
25+
* function MyComponent() {
26+
* const { data, timestamp } = useAppKitEvents((event) => {
27+
* console.log('Event occurred:', event.data.event);
28+
* });
29+
*
30+
* return (
31+
* <View>
32+
* <Text>Last event: {data?.event}</Text>
33+
* <Text>Time: {timestamp}</Text>
34+
* </View>
35+
* );
36+
* }
37+
* ```
38+
*/
739
export function useAppKitEvents(callback?: (newEvent: EventsControllerState) => void) {
8-
useAppKit(); // Use the hook for checks
40+
useAppKitContext();
941
const { data, timestamp } = useSnapshot(EventsController.state);
1042

1143
useEffect(() => {
@@ -21,11 +53,39 @@ export function useAppKitEvents(callback?: (newEvent: EventsControllerState) =>
2153
return { data, timestamp };
2254
}
2355

56+
/**
57+
* Hook to subscribe to a specific AppKit event
58+
*
59+
* @remarks
60+
* This hook allows you to listen for a specific event type rather than all events.
61+
* It's more efficient than `useAppKitEvents` when you only care about a particular event.
62+
*
63+
* @param event - The specific event name to subscribe to (e.g., 'MODAL_OPEN', 'CONNECT_SUCCESS')
64+
* @param callback - Callback function invoked when the specified event occurs
65+
*
66+
* @throws {Error} If used outside of an AppKitProvider
67+
*
68+
* @example
69+
* ```tsx
70+
* function MyComponent() {
71+
* useAppKitEventSubscription('CONNECT_SUCCESS', (event) => {
72+
* console.log('Wallet connected!', event.data);
73+
* });
74+
*
75+
* useAppKitEventSubscription('DISCONNECT_SUCCESS', (event) => {
76+
* console.log('Wallet disconnected!', event.data);
77+
* });
78+
*
79+
* return <View>{/ Your component /}</View>;
80+
* }
81+
* ```
82+
*/
83+
2484
export function useAppKitEventSubscription(
2585
event: EventName,
2686
callback: (newEvent: EventsControllerState) => void
2787
) {
28-
useAppKit(); // Use the hook for checks
88+
useAppKitContext();
2989

3090
useEffect(() => {
3191
const unsubscribe = EventsController?.subscribeEvent(event, callback);

packages/appkit/src/hooks/useAppKitLogs.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { useContext, useMemo } from 'react';
1+
import { useMemo } from 'react';
22
import { useSnapshot } from 'valtio';
33
import { LogController, type LogEntry, type LogLevel } from '@reown/appkit-core-react-native';
4-
import { AppKitContext } from '../AppKitContext';
4+
import { useAppKitContext } from './useAppKitContext';
55

66
export interface UseAppKitLogsReturn {
77
/**
@@ -65,15 +65,7 @@ export interface UseAppKitLogsReturn {
6565
* ```
6666
*/
6767
export const useAppKitLogs = (): UseAppKitLogsReturn => {
68-
const context = useContext(AppKitContext);
69-
70-
if (context === undefined) {
71-
throw new Error('useAppKitLogs must be used within an AppKitProvider');
72-
}
73-
74-
if (!context.appKit) {
75-
throw new Error('AppKit instance is not yet available in context.');
76-
}
68+
useAppKitContext();
7769

7870
const { logs } = useSnapshot(LogController.state);
7971

packages/appkit/src/hooks/useAppKitState.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,43 @@
22
import { useMemo } from 'react';
33
import { useSnapshot } from 'valtio';
44
import { ConnectionsController, ModalController } from '@reown/appkit-core-react-native';
5-
import { useAppKit } from './useAppKit';
5+
import { useAppKitContext } from './useAppKitContext';
6+
7+
/**
8+
* Hook to access the overall state of the AppKit modal and connection
9+
*
10+
* @remarks
11+
* This hook provides a high-level view of the AppKit's current state, including
12+
* whether the modal is open, if it's loading, connection status, and the active chain.
13+
* It's useful for coordinating UI elements with the AppKit's state.
14+
*
15+
* @returns An object containing:
16+
* - `isOpen`: Whether the AppKit modal is currently open
17+
* - `isLoading`: Whether the AppKit is in a loading state
18+
* - `isConnected`: Whether a wallet is currently connected
19+
* - `chain`: The currently active blockchain network
20+
*
21+
* @throws {Error} If used outside of an AppKitProvider
22+
*
23+
* @example
24+
* ```tsx
25+
* function MyComponent() {
26+
* const { isOpen, isLoading, isConnected, chain } = useAppKitState();
27+
*
28+
* return (
29+
* <View>
30+
* <Text>Modal: {isOpen ? 'Open' : 'Closed'}</Text>
31+
* <Text>Loading: {isLoading ? 'Yes' : 'No'}</Text>
32+
* <Text>Connected: {isConnected ? 'Yes' : 'No'}</Text>
33+
* {chain && <Text>Chain: {chain.name}</Text>}
34+
* </View>
35+
* );
36+
* }
37+
* ```
38+
*/
639

740
export function useAppKitState() {
8-
useAppKit(); // Use the hook for checks
41+
useAppKitContext();
942
const { activeAddress: address, connection, networks } = useSnapshot(ConnectionsController.state);
1043
const { open, loading } = useSnapshot(ModalController.state);
1144

packages/appkit/src/hooks/useAppKitTheme.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useMemo } from 'react';
22
import { useSnapshot } from 'valtio';
33
import type { ThemeMode, ThemeVariables } from '@reown/appkit-common-react-native';
44
import { ThemeController } from '@reown/appkit-core-react-native';
5-
import { useAppKit } from './useAppKit';
5+
import { useAppKitContext } from './useAppKitContext';
66

77
/**
88
* Interface representing the result of the useAppKitTheme hook
@@ -62,7 +62,7 @@ export interface UseAppKitThemeReturn {
6262
* ```
6363
*/
6464
export function useAppKitTheme(): UseAppKitThemeReturn {
65-
useAppKit(); // Use the hook for checks
65+
useAppKitContext();
6666
const { themeMode, themeVariables } = useSnapshot(ThemeController.state);
6767

6868
const stableFunctions = useMemo(

packages/appkit/src/hooks/useProvider.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useMemo } from 'react';
33
import { useSnapshot } from 'valtio';
44
import { ConnectionsController, LogController } from '@reown/appkit-core-react-native';
55
import type { Provider, ChainNamespace } from '@reown/appkit-common-react-native';
6+
import { useAppKitContext } from './useAppKitContext';
67

78
/**
89
* Interface representing the result of the useProvider hook
@@ -29,14 +30,12 @@ interface ProviderResult {
2930
*
3031
* if (provider) {
3132
* // Use the provider for blockchain operations
32-
* const balance = await provider.request({
33-
* method: 'eth_getBalance',
34-
* params: [address, 'latest']
35-
* });
33+
* const balance = await provider.request({...});
3634
* }
3735
* ```
3836
*/
3937
export function useProvider(): ProviderResult {
38+
useAppKitContext();
4039
const { connection } = useSnapshot(ConnectionsController.state);
4140

4241
const returnValue = useMemo(() => {

packages/appkit/src/hooks/useWalletInfo.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,41 @@
11
import { useMemo } from 'react';
22
import { useSnapshot } from 'valtio';
33
import { ConnectionsController } from '@reown/appkit-core-react-native';
4-
import { useAppKit } from './useAppKit';
4+
import { useAppKitContext } from './useAppKitContext';
55

6+
/**
7+
* Hook to access information about the currently connected wallet
8+
*
9+
* @remarks
10+
* This hook provides access to metadata about the connected wallet, such as its name,
11+
* icon, and other identifying information. It automatically subscribes to wallet info
12+
* changes via valtio.
13+
*
14+
* @returns An object containing:
15+
* - `walletInfo`: Metadata about the currently connected wallet (name, icon, etc.)
16+
*
17+
* @example
18+
* ```tsx
19+
* function MyComponent() {
20+
* const { walletInfo } = useWalletInfo();
21+
*
22+
* return (
23+
* <View>
24+
* {walletInfo && (
25+
* <>
26+
* <Image source={{ uri: walletInfo.icon }} />
27+
* <Text>{walletInfo.name}</Text>
28+
* </>
29+
* )}
30+
* </View>
31+
* );
32+
* }
33+
* ```
34+
*
35+
* @throws {Error} If used outside of an AppKitProvider
36+
*/
637
export function useWalletInfo() {
7-
useAppKit(); // Use the hook for checks
38+
useAppKitContext();
839
const { walletInfo: walletInfoSnapshot } = useSnapshot(ConnectionsController.state);
940

1041
const walletInfo = useMemo(() => ({ walletInfo: walletInfoSnapshot }), [walletInfoSnapshot]);

0 commit comments

Comments
 (0)