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.