0.1.2 • Published 1 year ago

@typecastdev/react-lib v0.1.2

Weekly downloads
-
License
ISC
Repository
github
Last release
1 year ago

@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:

VersionRelease DateNotes
0.1.211/26/2022UXFlag 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.131/08/2022First stable release of @typecastdev/react-lib. initializeTypecast and Cast released.

Table of Contents

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 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.

initializeTypecast will make a call to our API and retrieve changes for your app based on the orgKey and the userId 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 corresponding Customer with the correct userId. Please reference our Typecast Platform docs for more details about creating an Customer.

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 after 3.7s if changes can not be loaded. In the abort state no Cast 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 called initializeTypecast and looking for a call to evaluate. 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 to Casts 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 our UX Change in app.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 in Dashboard.js rather than Callout.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 in initializeTypecast.

In the case of duplicate keys setUserData will override value of the duplicate key where the last call to setUserData 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 a Promise.

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
0.1.2-3

2 years ago

0.1.2-5

2 years ago

0.1.2-4

2 years ago

0.1.2-11

2 years ago

0.1.2-10

2 years ago

0.1.2-7

2 years ago

0.1.2-6

2 years ago

0.1.2-9

2 years ago

0.1.2-8

2 years ago

0.1.2

1 year ago

0.1.2-2

2 years ago

0.1.2-1

2 years ago

0.1.2-0

2 years ago

0.1.1

2 years ago

0.1.0-3

2 years ago

0.1.0-2

2 years ago

0.1.0-1

2 years ago

0.1.0-0

2 years ago

0.0.2-4

2 years ago

0.0.2-3

2 years ago

0.0.2-2

2 years ago

0.0.2-1

2 years ago

0.0.2-0

2 years ago