Skip to main content

Basic React Usage

Causal works with structured features as opposed to boolean flags. The TypeScript SDK is custom to your features and provides robust type safety and deep auto completion. The definition of the RatingBox feature that this example uses is:

feature RatingBox {
args {
"The product that we are collecting ratings for"
product: String!
}

output {
"The text next to the stars that prompts the visitor to rate the product"
callToAction: String! = "Rate this product!"

"The button text for the user submit a review."
actionButton: String! = "Send Review"
}

"Occurs each time a rating is collected"
event Rating {
stars: Int!
}
}

The example repo contains the generated typescript SDK. If you'd like to regenerate it, you can by invoking the compiler. In the getting-started directory, run the following:

npx causalc --typescript causal.ts causal.fdl

Code Walk Through

Import from Causal

import { useRouter } from "next/router";
import { useState } from "react";
import { qb, Session, SessionContext, useFeature } from "../causal";
import { RatingWidget } from "../components/RatingWidget";
import { getOrGenDeviceId, products } from "../utils";

Create a session and put it into context

Creating a session requires a deviceId, which is specific to how you uniquely identify browsers. This example uses the utility function getOrGenDeviceId that creates a random uuid and stores it in a cookie.

Putting the the session in a context makes the session session available to any child component using the the standard React context provider pattern. You can, of course, also pass and use the session directly if you prefer.

These steps are typically done once in a root component, such as _app.tsx. You don't need to do this anew for each feature. For the simplicity of the example though, we do it at the page level instead.


export default function Page() {
const router = useRouter();

const session = new Session({ deviceId: getOrGenDeviceId(router) });

const product = products[router.query.pid as keyof typeof products];
if (product == undefined) {
return <></>; // Product not found
}

return (
<SessionContext.Provider value={session}>
<ProductInfo product={product} />
</SessionContext.Provider>
);
}

Create a query, and use the React hook

Use useFeature to request the feature. useFeature utilizes the session that was put into the context earlier. If you'd like, you can also manually pass it a session.

export function ProductInfo({
product,
}: {
product: { name: string; url: string; next: string };
}) {
const [rating, setRating] = useState(0);
const router = useRouter();

const ratingBox = useFeature(qb().getRatingBox({ product: product.name }));

Use the feature

Test the feature flag. All features come with a built in on/off feature flag.

  return (
<div className="center">
<h1>{product.name}</h1>
<img src={product.url} alt="product image" />

{ratingBox != "OFF" && (
<>

Use the feature data, and wire up events

          {/* use impression data */}
<h3>{ratingBox?.callToAction}</h3>
<RatingWidget
curRating={rating}
onSetRating={(newRating) => {
setRating(newRating);
// wire up events
ratingBox?.signalRating({ stars: newRating });
}}
/>
<a href={router.route + "?pid=" + product.next}>Rate Another</a>
</>
)}
</div>
);
}

Congrats

You've finished the basic React walk through.