@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
initializeTypecast
function. - 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-lib
Using yarn
yarn add @typecastdev/react-lib
Using pnpm
pnpm install @typecastdev/react-lib
Verify 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 Cast
s 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.
initializeTypecast
will make a call to our API and retrieve changes for your app based on theorgKey
and theuserId
specified.
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
userId
to "customer@yourclient.com". But this can be anything, as long as you create a correspondingCustomer
with 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.
initializeTypecast
will abort after3.7s
if changes can not be loaded. In the abort state noCast
will enable across the app.Note that you can check if the initialize function is working by checking the
Network
tab on your browser on the page you calledinitializeTypecast
and 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
Cast
is waiting for changes to be loaded (up to 500ms), a loading spinner will appear for the customer, you can pass your own loading component toCasts
if 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 Payload
of ourUX Change
inapp.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
Callout
component inDashboard.js
rather 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:
setUserData
will set/update user data for the userId passed ininitializeTypecast
.In the case of duplicate keys
setUserData
will override value of the duplicate key where the last call tosetUserData
was 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
async
and 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.2
react-dom: ^17.0.2
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago