Feature flags are commonly used inside of React JS applications to toggle between components or routes.
There are two component parts to this - the Context, and consuming the Context.
Context
Contexts have two primary purposes:
Fetch data from Webtrends Optimize
Expose methods that allow this data to be consumed anywhere in the application.
The below code illustrates how you might construct a Context.
Note: This is not production-ready code - you should wrap API calls in try-catches, handle empty scenarios, etc.
// WTOFlagsContext.js
import React, { createContext, useState, useContext, useEffect } from "react";
const WTOFlagsContext = createContext();
export const WTOFlagsProvider = ({ children }) => {
const [data, setData] = useState({}); // State for fetched data
useEffect(() => {
const fetchData = async () => {
let ssFlags = sessionStorage.getItem("wto_flags");
if(ssFlags){
// Will be string by default, parse into JSON
ssFlags = JSON.parse(ssFlags);
// Set state
setData(ssFlags);
} else {
// Make API call
let resp = await fetch("https://ots.webtrends-optimize.com/...");
resp = await resp.json();
// Transform response into flags
// Set state
setData(resp);
// Save data into SS
sessionStorage.setItem("wto_flags", JSON.stringify(jsonData));
}
};
fetchData(); // Call the function when the component mounts
}, []);
return (
<WTOFlagsContext.Provider value={{ data }}>
{children}
</WTOFlagsContext.Provider>
);
};
Note: The actual API call to OTS has many options, see the API guide for full details of how to communicate with it.
Consuming the flags
Given the exposed provider and data, we are then able to import this component and fetch the data when we need to.
The below example illustrates an approach for rendering different
import React from "react";
import { Routes, Route } from "react-router-dom";
import { useWTOFlags } from "./WTOContext";
const ProductsViewA = () => <h1>Products View Control</h1>;
const ProductsViewB = () => <h1>Products View Variation</h1>;
const AppRoutes = () => {
const { data } = useWTOFlags();
return (
<Routes>
{/* ... */}
<Route
path="/products/*"
element={(data.ta_ProductViewAB || null) === 'variation' ? <ProductsViewB /> : <ProductsViewA />}
/>
</Routes>
);
};
export default AppRoutes;