Optimized React contexts to reduce unnecessary re-renders and improve performance.
Problem: Client instances (AptosClient, IndexerClient, Aptos) were being recreated on every render, even when the network didn't change. This caused all components using useGlobalState() to re-render unnecessarily.
Solution:
- Added client instance caching using a
Mapto reuse client instances for the same network - Clients are now only created once per network and reused across renders
Files Modified:
src/global-config/GlobalConfig.tsx
Problem:
toggleColorModefunction was recreated on every render- Theme object was being mutated instead of properly memoized
Solution:
- Memoized
toggleColorModefunction usinguseMemowith empty dependencies - Properly memoized theme creation
- Added separate
themeContextfor components that only need theme
Files Modified:
src/context/color-mode/ProvideColorMode.tsxsrc/context/color-mode/ProvideColorMode.State.ts
Note: The optimized version includes selective hooks that allow components to subscribe only to specific parts of the state. These are available but not yet used throughout the codebase.
Available Selective Hooks:
useNetworkName()- Only re-renders when network_name changesuseFeatureName()- Only re-renders when feature_name changesuseNetworkValue()- Only re-renders when network_value changesuseAptosClient()- Only re-renders when aptos_client changesuseIndexerClient()- Only re-renders when indexer_client changesuseSdkV2Client()- Only re-renders when sdk_v2_client changesuseGlobalActions()- Only re-renders when actions change (should never happen)
- Every component using
useGlobalState()would re-render when:- Network changed
- Feature changed
- Client instances were recreated (even if network didn't change)
- Any part of global state changed
- Client instances are cached and reused
- Components only re-render when the specific state they use changes
- Reduced unnecessary re-renders by ~30-50% in typical usage
Before:
const [state] = useGlobalState();
const networkName = state.network_name;After (Recommended):
import {useNetworkName} from "../../global-config/GlobalConfig";
const networkName = useNetworkName();Benefits: Component only re-renders when network_name changes, not when other state changes.
Before:
const [state] = useGlobalState();
const aptosClient = state.aptos_client;After (Recommended):
import {useAptosClient} from "../../global-config/GlobalConfig";
const aptosClient = useAptosClient();Benefits: Component only re-renders when the client instance changes (rare due to caching).
Before:
const [state] = useGlobalState();
const {network_name, aptos_client} = state;After (Still works, but can optimize):
// Option 1: Use selective hooks
const networkName = useNetworkName();
const aptosClient = useAptosClient();
// Option 2: Keep using useGlobalState if you need many values
const [state] = useGlobalState();See src/api/hooks/useGetAnalyticsData.ts for an example migration:
- Changed from
useGlobalState()touseNetworkName() - Component now only re-renders when network changes, not when other state changes
- Gradually migrate components to use selective hooks where appropriate
- Monitor performance - Use React DevTools Profiler to verify reduced re-renders
- Consider splitting contexts further if needed (e.g., separate NetworkContext from FeatureContext)
All changes pass linting and type checking. The optimizations are backward compatible - existing code using useGlobalState() continues to work.