# React

## Setup the SDK

### Install Packages

```shell
npm install @neonblue-ai/react-bindings
```

### Initialize the SDK

Wrap your application with `NeonBlueProvider`:

{% code title="App.jsx" %}

```jsx
import { NeonBlueProvider } from "@neonblue-ai/react-bindings";

function App() {
  return (
    <NeonBlueProvider
      sdkKey="client--00000000-0000-0000-0000-000000000000"
      user={{ userId: "00000000" }}
    >
      <MyComponent />
    </NeonBlueProvider>
  );
}
```

{% endcode %}

For connecting to the staging instance:

{% code title="App.jsx" %}

```jsx
import { NeonBlueProvider } from "@neonblue-ai/react-bindings";

function App() {
  return (
    <NeonBlueProvider
      sdkKey="client--00000000-0000-0000-0000-000000000000"
      user={{ userId: "00000000" }}
      options={{
        networkConfig: {
          api: "https://api.staging.neonwhite.dev/v1/sdk",
        }
      }}
    >
      <MyComponent />
    </NeonBlueProvider>
  );
}
```

{% endcode %}

You can also pass a pre-initialized client:

```jsx
import NeonBlueClient from "@neonblue-ai/js-client";
import { NeonBlueProvider } from "@neonblue-ai/react-bindings";

const client = new NeonBlueClient(
  "client--00000000-0000-0000-0000-000000000000",
  { userId: "123" },
);
await client.initializeAsync();

function App() {
  return (
    <NeonBlueProvider client={client}>
      <MyComponent />
    </NeonBlueProvider>
  );
}
```

## Use the SDK

### useExperiment Hook

The `useExperiment` hook fetches an experiment asynchronously and provides loading state:

{% code title="MyComponent.jsx" %}

```jsx
import { useExperiment } from "@neonblue-ai/react-bindings";

function MyComponent() {
  const { experiment, isLoading } = useExperiment("my_experiment");

  if (isLoading) {
    return <Loading />;
  }

  return (
    <div>
      <img
        src={experiment?.get(
          "img_url",
          "https://fallback.example.com/default.jpg",
        )}
      />
      <h1>{experiment?.get("h1", "Default Headline")}</h1>
    </div>
  );
}
```

{% endcode %}

### useNeonBlueClient Hook

Access the client directly for more control:

{% code title="UseClient.jsx" %}

```jsx
import { useNeonBlueClient } from "@neonblue-ai/react-bindings";

function MyComponent() {
  const { client, getExperimentAsync, isLoading } = useNeonBlueClient();

  const handleClick = async () => {
    const experiment = await getExperimentAsync("checkout_test");
    console.log(experiment.get("variant", "control"));
  };

  return <button onClick={handleClick}>Click me</button>;
}
```

{% endcode %}

### Changing Users

When a user logs in or out, update the `user` prop on the provider:

{% code title="AuthExample.jsx" %}

```jsx
function App() {
  // Start anonymous - empty object uses auto-generated StableId
  const [user, setUser] = useState({});

  const handleLogin = (userId) => {
    setUser({ userId });
  };

  const handleLogout = () => {
    // Revert to anonymous
    setUser({});
  };

  return (
    <NeonBlueProvider
      sdkKey="client--00000000-0000-0000-0000-000000000000"
      user={user}
    >
      <MyComponent onLogin={handleLogin} onLogout={handleLogout} />
    </NeonBlueProvider>
  );
}
```

{% endcode %}

The provider will automatically re-initialize with the new user and fetch fresh experiment assignments.

### Loading States

The provider accepts a `loadingComponent` prop to show while initializing:

{% code title="AppWithLoading.jsx" %}

```jsx
<NeonBlueProvider
  sdkKey="client--00000000-0000-0000-0000-000000000000"
  user={{ userId: "123" }}
  loadingComponent={<LoadingSpinner />}
/>
```

{% endcode %}
