/** * Copyright 2025-2026 Wingify Software Pvt. Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import React, { useEffect, useState, ReactNode, useMemo } from 'react'; import { init, IVWOContextModel, IVWOClient, IVWOOptions } from './sdk'; import { VWOContext } from './VWOContext'; import { initLogger } from './services/LoggerService'; import { LogMessageEnum } from './enum/LogMessageEnum'; import { logHookError } from './utils/LogMessageUtil'; export interface VWOProviderWithClient { client: IVWOClient; userContext?: IVWOContextModel; children: ReactNode; fallbackComponent?: ReactNode; } export interface VWOProviderWithConfig { config: IVWOOptions; userContext?: IVWOContextModel; children: ReactNode; fallbackComponent?: ReactNode; } export type IVWOProvider = VWOProviderWithClient | VWOProviderWithConfig; /** * VWOProvider component to provide VWO client and configuration context to child components. * * @param props - The props for the VWOProvider component. * @returns A React element that provides the VWO client and configuration context to child components. */ export function VWOProvider(props: IVWOProvider): React.ReactElement { const { userContext, children, fallbackComponent } = props; const client = 'client' in props ? props.client : null; const config = 'config' in props ? props.config : null; const [vwoClient, setVwoClient] = useState(client || null); const [context, setContext] = useState(userContext || null); const [isReady, setIsReady] = useState(false); const memoizedConfig = useMemo(() => config || client?.options, []); let logger; // Initialize the VWO SDK instance only once when the component mounts or if config is updated useEffect(() => { try { logger = initLogger(client?.options || config); if (config && vwoClient) { logger.warn(LogMessageEnum.VWO_PROVIDER_CLIENT_CONFIG_WARNING); } if (vwoClient) { setIsReady(true); return; } else if (!config) { logger.error(LogMessageEnum.VWO_PROVIDER_CONFIG_REQUIRED); return; } const initializeVWO = async () => { if (!vwoClient && config) { // Initialize the VWO SDK instance if vwoClient is not already initialized const instance = await init(config); setVwoClient(instance); setIsReady(true); } }; // Initialized only once if (!vwoClient && config) { initializeVWO(); } } catch (error) { logHookError(logger, error, LogMessageEnum.VWO_SDK_INITIALIZATION_FAILED); } }, [memoizedConfig]); // Re-run only when config changes return ( {fallbackComponent && !isReady ? fallbackComponent : children} ); };