> ## Documentation Index
> Fetch the complete documentation index at: https://docs.frankieone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# React

> This guide walks you through integrating OneSDK with React, providing you with a solid foundation for building secure and efficient KYC workflows.

## Quick Start

<Steps>
  <Step title="Create Your React Project">
    Choose your preferred bundler:

    <Tabs>
      <Tab title="Vite">
        ```shell theme={null}
        npm create vite@latest my-react-app -- --template react
        ```
      </Tab>

      <Tab title="Create React App">
        ```shell theme={null}
        npx create-react-app my-app
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Install Dependencies">
    ```shell theme={null}
    cd my-react-app
    npm install
    npm install @frankieone/one-sdk
    ```
  </Step>

  <Step title="Start Development">
    ```shell theme={null}
    npm run dev  # for Vite
    # or
    npm start    # for Create React App
    ```
  </Step>
</Steps>

## Configuration

<AccordionGroup>
  <Accordion title="Vite Configuration">
    Add this configuration to your `vite.config.js`:

    ```javascript theme={null}
    import { defineConfig } from "vite";
    import react from "@vitejs/plugin-react";

    export default defineConfig({
      plugins: [react()],
      define: {
        "process.env": {},
      },
    });
    ```
  </Accordion>

  <Accordion title="Environment Setup">
    <Callout icon="star" color="#3DD892" iconType="regular">
      Based on your build tool and/or framework, you may have a different prefix to the environment variables,
      e.g. if you're using Vite, your env prefix is going to be "VITE\_" instead of "REACT\_APP\_"
    </Callout>

    Create a `.env` file with your credentials:

    ```shell theme={null}
    REACT_APP_CUSTOMER_ID=your_customer_id
    REACT_APP_API_KEY=your_api_key
    REACT_APP_CHILD_ID=your_child_id    # optional
    ```
  </Accordion>
</AccordionGroup>

## Integration with React

### Custom Hook Implementation

<Tabs>
  <Tab title="useOneSDK Hook">
    ```typescript theme={null}
    import OneSDK from "@frankieone/one-sdk";
    import { useEffect, useRef, useState } from "react";

    interface OneSDKConfig {
      mode: 'development' | 'production';
      recipe: {
        form: {
          provider: {
            name: string;
          };
        };
      };
    }

    interface UseOneSDKProps {
      config?: OneSDKConfig;
    }

    const useOneSDK = ({ config }: UseOneSDKProps) => {
      const [oneSDKInstance, setOneSDKInstance] = useState(null);
      const [error, setError] = useState(null);
      const [loading, setLoading] = useState(false);
      const initializedRef = useRef(false);

      const generateToken = async () => {
        try {
          const tokenRawAsync = await fetch(
            "https://backend.latest.frankiefinancial.io/auth/v2/machine-session",
            {
              method: "POST",
              headers: {
                authorization: `machine ${btoa(
                  `${process.env.REACT_APP_CUSTOMER_ID}:${process.env.REACT_APP_API_KEY}`
                )}`,
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                permissions: {
                  preset: "one-sdk",
                  reference: `demo-${new Date().toISOString()}`,
                },
              }),
            }
          );
          return await tokenRawAsync.json();
        } catch (error) {
          setError(error.message);
          return null;
        }
      };

      const generateOneSDKInstance = async () => {
        setLoading(true);
        try {
          const token = await generateToken();
          if (!token) return;

          const defaultConfig = {
            mode: "development",
            recipe: {
              form: {
                provider: {
                  name: "react",
                },
              },
            },
          };

          const oneSDKInit = await OneSDK({
            session: token,
            ...(config || defaultConfig),
          });

          setOneSDKInstance(oneSDKInit);
        } catch (error) {
          setError(error.message);
        } finally {
          setLoading(false);
        }
      };

      useEffect(() => {
        if (!initializedRef.current) {
          generateOneSDKInstance();
          initializedRef.current = true;
        }
      }, [config]);

      return { oneSDKInstance, error, loading };
    };

    export default useOneSDK;
    ```
  </Tab>

  <Tab title="Usage Example">
    ```tsx theme={null}
    import useOneSDK from './hooks/useOneSDK';

    const KYCForm = () => {
      const { oneSDKInstance, error, loading } = useOneSDK({
        config: {
          mode: 'development',
          recipe: {
            form: {
              provider: {
                name: 'react',
              },
            },
          },
        },
      });

      if (loading) return <div>Loading OneSDK...</div>;
      if (error) return <div>Error: {error}</div>;
      if (!oneSDKInstance) return <div>OneSDK not initialized</div>;

      return (
        <div>
          {/* Your KYC form implementation using oneSDKInstance */}
        </div>
      );
    };

    export default KYCForm;
    ```
  </Tab>
</Tabs>

### Best Practices

<Columns>
  <Card title="Error Handling" icon="shield-check">
    * Always handle token generation errors - Provide meaningful error messages
    * Implement proper error boundaries
  </Card>

  <Card title="Security" icon="lock">
    * Never expose API keys in client-side code
    * Use environment variables
    * Implement proper token management
  </Card>

  <Card title="Performance" icon="bolt">
    * Use React.memo for expensive renders
    * Implement proper cleanup in `useEffect`
    * Avoid unnecessary re-renders
  </Card>

  <Card title="State Management" icon="database">
    * Use proper state management patterns
    * Implement loading states
    * Handle edge cases properly
  </Card>
</Columns>

<Callout icon="bell" color="#FFCA16" iconType="regular">
  Remember to handle token expiration and implement proper refresh mechanisms in
  a production environment.
</Callout>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Common Issues">
    * **Token Generation Fails**: Verify your credentials and network connection
    * **SDK Initialization Errors**: Check configuration object format
    * **Component Re-rendering**: Implement proper memoization
  </Accordion>

  <Accordion title="Environment Variables">
    * **Vite**: Ensure variables are prefixed with `VITE_`
    * **Create React App**: Ensure variables are prefixed with `REACT_APP_`
    * **Development**: Verify `.env` file location
  </Accordion>
</AccordionGroup>

## Next Steps

<Columns>
  <Card title="Sample Implementation" icon="code" href="/docs/embedded-flows/split-flow">
    View complete implementation examples
  </Card>

  <Card title="API Reference" icon="book" href="/docs/reference/authentication">
    Explore the complete API documentation
  </Card>
</Columns>
