@typecastdev/react-lib v0.1.2
@typecastdev/react-lib
Add Casts to your React App and dynamically manage them through Typecast
Documentation
For general documentation, please refer to docs.typecast.dev
Latest Version: v0.1.2
Support and Maintenance
Please do not hesitate to send us an email with any questions/concerns/problems.
Maintainers:
- Support - bailey@typecast.dev
Versioning
Note: Please install stable versions, if you would like to test a pre-release version please email one of the Maintainers.
Stable Versions:
| Version | Release Date | Notes |
|---|---|---|
| 0.1.2 | 11/26/2022 | UXFlag becomes Cast, orgId becomes orgKey. New functions exposed through SDK: cleanUp, getUserData, setUserData, subscribeToTypecastLogs, and getTypecastLogs. New action type props that passes props from app.typecast.dev to components wrapped in a Cast. |
| 0.1.1 | 31/08/2022 | First stable release of @typecastdev/react-lib. initializeTypecast and Cast released. |
Table of Contents
- Support and Maintenance
- Versioning
- Installing @typecastdev/react-lib into your codebase.
- Intializing Typecast with the
initializeTypecastfunction. - Creating your first
Cast. - Working with different Cast types
- Setting & getting user data
- Advanced Functionality
- Troubleshooting
Installing @typecastdev/react-lib into your codebase
Install the @typecastdev/react-lib package.
In the root folder of your app run one of the following commands to install @typecastdev/react-lib, depending on the package manager you use.
Note that if you do not use versions of packages listed in our peer dependencies list, you may have trouble installing our package. Please don't hesitate to contact our Maintainers, or check our troubleshooting section.
Using npm
npm install @typecastdev/react-libUsing yarn
yarn add @typecastdev/react-libUsing pnpm
pnpm install @typecastdev/react-libVerify the package installed correctly
Once you've installed the package, make sure you should see the following in your package.json
{
"name": "your-web-app",
"dependencies": {
...
"@typecastdev/react-lib": "^0.1.2",
...
},
...
}Congratulations! You've successfully installed @typecastdev/react-lib in your codebase!
Intializing Typecast with the initializeTypecast function.
Note: Please ensure you have completed the previous step before starting this step.
Import Typecast into your codebase.
Normally Typecast will need to be imported wherever you use anything from our SDK
import * as Typecast from '@typecastdev/react-lib';
// for specific function/component imports
import { Cast } from '@typecastdev/react-lib`;Initialize Typecast with the initializeTypecast function.
IMPORTANT: Ensure that your call to initializeTypecast is implemented in code that your user reaches frequently!
This method is required to be called somewhere in your codebase for any of your Casts to function properly.
If this method is not called, is called incorrectly, or fails, Cast components will default to rendering the children passed to them.
Find a useEffect or appropriate spot to call initializeTypecast (normally right after a user logs in or in a nav bar.)
It is possible to call initializeTypecast several times in your codebase, but not recommended.
initializeTypecastwill make a call to our API and retrieve changes for your app based on theorgKeyand theuserIdspecified.
It is very important that the call to initializeTypecast is placed in a spot in your app that your user encounters frequently (i.e. a Dashboard.js or a Home.js page, or a NavBar component). This way you can ensure that changes load before your customers encounter their first Cast components.
Calling initializeTypecast in an example file: Dashboard.js.
Note that in this case we are hard coding our
userIdto "customer@yourclient.com". But this can be anything, as long as you create a correspondingCustomerwith the correctuserId. Please reference our Typecast Platform docs for more details about creating anCustomer.
const DashboardPage = () => {
useEffect(() => {
// It is not required to await this call.
Typecast.initializeTypecast({
orgKey: "c318a807-a6b6-4b6b-9b22-4641f505556a",
userId: "customer@yourclient.com"
});
});
...
}We can also optionally add a handler function in the second parameter of the initializeTypecast method to trigger when Typecast is initialized.
const DashboardPage = () => {
const handleTypecastInitialized = (response) => console.log(response);
useEffect(() => {
Typecast.initializeTypecast({...}, handleTypecastInitialized);
});
...
}Now that we have called initializeTypecast, we can begin to add Cast components to our code.
initializeTypecastwill abort after3.7sif changes can not be loaded. In the abort state noCastwill enable across the app.Note that you can check if the initialize function is working by checking the
Networktab on your browser on the page you calledinitializeTypecastand looking for a call toevaluate. It should be have a status of 200.
Creating your first Cast
Note: Please ensure you have completed the previous step before starting this step.
Add a Cast to an example Dashboard.js file
In this case we want to hide some content from our customer customer@yourclient.com (assuming in our Typecast platform we have created a UX Change with name: HideFromManager, action: hide for a User Group with Trigger user_type=="manager).
Loading note: For the duration of time that the
Castis waiting for changes to be loaded (up to 500ms), a loading spinner will appear for the customer, you can pass your own loading component toCastsif preferred.
Right now this is what our code looks like:
import * as React from "react";
import * as Typecast from '@typecastdev/react-lib';
const DashboardPage = () => {
useEffect(() => {
Typecast.initializeTypecast({
orgKey: "c318a807-a6b6-4b6b-9b22-4641f505556a",
userId: "customer@yourclient.com"
});
});
return (
<YourComponent>
<YourComponentHeader title="Welcome to Typecast" />
<YourComponentContent>Something a manager shouldn't see</YourComponentContent>
</YourComponent>
)
}
export default DashboardPage;Wrap components desired to be managed through Typecast with a Cast
Adding a Cast to your components is as easy as wrapping the parts of your component you'd like to manage externally with a Cast.
return (
<YourComponent>
<YourComponentHeader title="Welcome to Typecast" />
// It's important to provide a `name` for your Cast.
// This will correspond to the UX Change created on the Typecast platform.
<Typecast.Cast name="HideFromManager">
<YourComponentContent>Something a manager shouldn't see</YourComponentContent>
</Typecast.Cast>
</YourComponent>
)It's as simple as that. Now you can create as many Cast components as you'd like in your codebase!
This completes our installation and first Cast section. There are more powerful ways to use Typecast, such as passing props to your wrapped components dynamically, and managing user state through Typecast. With these features, advanced rendering logic and dynamic content can be added to your product!
Completed Dashboard.js + Cast file overview
Congrats! We've successfully created our first Cast!
A view of our Dashboard.js component.
import * as React from "react";
import * as Typecast from '@typecastdev/react-lib';
const DashboardPage = () => {
useEffect(() => {
Typecast.initializeTypecast({
orgKey: "c318a807-a6b6-4b6b-9b22-4641f505556a",
userId: "customer@yourclient.com"
});
});
return (
<YourComponent>
<YourComponentHeader title="Welcome to Typecast" />
<Typecast.Cast name="HideFromManager">
<YourComponentContent>Something a manager shouldn't see</YourComponentContent>
</Typecast.Cast>
</YourComponent>
)
}
export default DashboardPage;Working with different Cast types
In this section we'll go over the different Cast types:
props type
With the props type, we're able to pass props to the component that we wrap with our Cast from our Typecast platform (app.typecast.dev). These props are passed to the component wrapped in the Cast prior to them rendering, and allow for dynamic content generation based on user data stored on our Typecast platform.
Note: props should be defined in the
Action Payloadof ourUX Changeinapp.typecast.dev. More details can be found in our Typecast Platform documentation.
Creating a Callout component with dynamic content
In this example we're going to be making an existing component named Callout manageable through the Typecast platform.
Our goal is to have the Callout dynamically open and show text for specific users to let them know about a new feature we're releasing.
Note: the following example does not cover creating a UX Change in the Typecast platform that correspond to this
Cast.
To accomplish this, we need to complete the following:
1. Wrap our Callout component where we'd like to effect a UX Change
2. Update our Callout component to support typecastProps
The two files we'll be editing are Dashboard.js and Callout.js
Dashboard.js:
// other imports are made here
...
import Callout from './Callout.js';
import * as Typecast from '@typecastdev/react-lib'
// `currentUser` is being passed to the Dashboard page from somewhere in the code
const Dashboard = ({ currentUser }) => {
useEffect(() => {
// initialized typecast for our Dashboard component
// note that currentUser is a string.
Typecast.initializeTypecast({
orgKey: "c318a807-a6b6-4b6b-9b22-4641f505556a",
userId: currentUser
});
});
// our not so special Dashboard
return (
<div>
<h1>This dashboard is from 2001!</h1>
<p>Hopefully your dashboard is better than ours...</p>
// Here our callout is called with no Cast
<Callout colour="green"/>
<div/>
)
}Callout.js:
// other imports are made here
...
import Popup from '@someUILibrary/Popup';
const Callout = ({ colour }) => {
return (
<Popup colour={colour} open={true}> I am a callout!</Popup>
)
}
export default Callout;Now let's wrap our Callout component with a Cast in Dashboard.js.
Note best practices: we recommend wrapping the components you'd like to manage in the files that you'd like to view UX Changes in rather than wrapping the component in its declaration file (wrapping our
Calloutcomponent inDashboard.jsrather thanCallout.js). This makes it easier to keep track of your Casts and ensures that they are explicit and maintainable.
Dashboard.js:
...
const Dashboard = ({ currentUser }) => {
...
// our not so special Dashboard
return (
<div>
<h1>This dashboard is from 2001!</h1>
<p>Hopefully your dashboard is better than ours...</p>
// Typecast.Cast will pass props to children components through the `typecastProps` prop. This needs to be handled inside the wrapped component.
// We do not need to add any additional props below to our Callout component.
<Typecast.Cast name="DashboardCallout">
<Callout colour="green"/>
</Typecast.Cast>
<div/>
)
}Finally, let's modify our Callout component to accept typecastProps.
For this example, we'll be expecting typecastProps to have two attributes (defined in our Typecast platform), typecastProps.text and typecastProps.open.
Callout.js:
// other imports are made here
...
import Popup from '@someUILibrary/Popup';
// Notice the addition of `typecastProps` to our component's props.
// This is an object that contains attributes that are defined in the `Action Payload` of a UX Change in the Typecast platform.
// Any component wrapped in a `Cast` that has `typecastProps` as a prop has access to the props sent from the Typecast platform.
const Callout = ({ colour, typecastProps }) => {
// getting props from `typecastProps`
const text = typecastProps?.text ?? "I am a callout"
const open = typecastProps?.open ?? true;
return (
<Popup colour={colour} open={open}>{text}</Popup>
)
}And there we have it. Now our Callout component on the Dashboard should open and render text dynamically based on the data passed by the Cast. In this case we have some default values for text and open. It is recommended to have default values for all typecastProps to ensure at runtime our components have fallback values if Typecast doesn't render, or our component is used without a Cast.
It is important that we define DashboardCallout as a UX Change on the Typecast platform, and ensure that text and open are in the Action Payload. More details can be found in our Typecast Platform documentation.
hide type
With the hide type, we're able to show or not show the children of Cast.
We covered an example of using the hide type in our Creating your first Cast documentation.
Setting & getting user data
Typecast offers a way to keep track of a users state with setUserData and getUserData. These functions allow you to send and retrieve data about the current user (passed in the initializeTypecast function) in different parts of your code without needing to modify existing global state logic (i.e. redux).
Set User data
You can set user data to Typecast by using the setUserData function. In the example below, we're trying to collect user state about a user clicking an ImportantButton. We'll set importantButtonClicked as true if they have.
Note:
setUserDatawill set/update user data for the userId passed ininitializeTypecast.In the case of duplicate keys
setUserDatawill override value of the duplicate key where the last call tosetUserDatawas made.
...
import { setUserData } from '@typecastdev/react-lib'
const ImportantButton = () => {
// now we can handle this state in other parts of our application
const handleImportantButtonClicked = (e) => {
setUserData({
importantButtonClicked: true
})
}
return (
<Button onClick={handleImportantButtonClicked}> Click me... if you dare!</Button>
)
}We can optionally specify to setUserData if we'd like to persist that data to the Typecast platform or not using the optional persist second parameter of setUserData (default is true). If persist is false, data that is set will only store on the local machine of the current user.
...
import { setUserData } from '@typecastdev/react-lib'
const ImportantButton = () => {
// with the addition of `false`, we do not persist this user data (i.e. `importantButtonClicked`) to the Typecast platform
const handleImportantButtonClicked = (e) => {
setUserData({
importantButtonClicked: true
}, false)
}
return (
<Button onClick={handleImportantButtonClicked}> Click me... if you dare!</Button>
)
}Get User data
We can retrieve userData that we set, or that we have defined in our Typecast platform, using the getUserData function.
Note: this function is
asyncand returns aPromise.
We can retrieve user data by specifiying the key parameter to getUserData, or get the userData object by providing no parameter to getUserData.
In this example, we want to determine if a user can see certain content based on if they have clicked the ImportantButton or not.
...
import { getUserData } from '@typecastdev/react-lib'
const ImportantContent = () => {
const [canSee, setCanSee] = useState(false);
// now we can handle this state in other parts of our application
useEffect(() => {
const fn = async () => {
// get data that we previously had set
const hasClickedImportantButton = await getUserData('importantButtonClicked');
setCanSee(hasClickedImportantButton);
}
fn();
});
return (
<>
{
canSee && (
<Content>Typecast is pretty awesome...</Content>
)
}
</>
)
}Advanced functionality
Logging
Subscribe to logs from Typecast by providing a handler for the Typecast.subscribeToTypecastLogs function (usually console.log).
You will then see logs from Typecast in your console (or wherever you handle logs).
For a list of all logs that Typecast collects during a session, you can also call the Typecast.getTypecastLogs() function, which returns an array of logs.
Beta Custom loading components
If you wish to use a custom loading component for a Cast, you can pass the loading component through the Cast LoadingComponent prop.
LoadingComponent must be of type
React.ReactNode.
import MyCustomLoadingComponent from './MyCustomLoadingComponent'
<Cast name="CastWithCustomLoadingComponent" LoadingComponent={MyCustomLoadingComponent}>
...
</Cast>Clean up
Remove user orgKey, and customerExternalId from their window.localStorage by calling the Typecast.cleanUp() function wherever you handle logging out.
Typecast caches those values to ensure that changes load even if initializeTypecast is not reached when a user loads a page.
Troubleshooting
In this section we'll go over some of the common issues encountered with the SDK.
Peer dependencies not matching
If you run into this issue while running the npm install, please try again with the command --legacy-peer-deps, and let us know about the peer dependency that is causing the issue.
Peer dependencies:
Note: the ^ symbol before a peer dependency indicates we support that version of the package and above.
react: ^17.0.2react-dom: ^17.0.2
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago