How to organize all the model interfaces and types in your TypeScript project

So many ways, so many good solutions. I do not think you can go very wrong regardless of the approach employed with your types. However, there are some benefits in few patterns that I prefer. As a rule of thumb, I do not want to search far away from my types. While the tool that you are using might provide a shortcut to search by name easily, and I do leverage it most of the time, it is crucial to find types easily when you do not know the name or when you are not sure if it already exists. The reason is mostly to avoid duplication and to ease the introduction of new developers in your project but also to find out if one of your teammates already coded a definition that you could reuse.

First of all, the approach I am using is subjective. It means that you have to take many choices that some people might or not agree with your team. I have worked in systems where all the components (views) were together, and all the test in one folder, and all the model in one folder. This is straightforward but come with the cost that when your application grows that these folders are neverending. It becomes hard to navigate. I also saw folder divided by team, which is okay until organization breakdown the structure and then it becomes a mess. I also seen some separation that works by model but mix all model files are a sibling to your views (in React your .tsx file, in Angular the .html), to your tests, etc. The approach is not bad, but when you start having more than one component or page using the same model you are stuck.

The approach I recommend is to have your source folder divided by domain of business. For example, under your “source” folder, you can have a “UserManagement”, a “Products”, an “Inventory”, a “Shipping” folder etc. The idea is at that point, you do not rely on the technology that you will use, neither how your application will separate the UI. Your user management might have 1 page or 10 pages, it doesn’t matter. The choice of these domains is subjective. You could avoid having “Inventory” and put everything under “Products”. It is up to you and your team to figure out how fined grained your want these domain folders.

Under each of these domain folders, you can start bringing some specification of your technologies. For example, with React, each of these folder has a “Actions”, “ContainerComponents”, “Middlewares”, “Models”, “PresentationComponents” and “Reducers”. Once again, you have some freedom. You can keep all your container and presentation into a single “components” folder. I like to divide them because I know that my containers are connected while my presentations are more reusable and not connected to Redux directly. Within each of these folders, I have my Typescript file (.ts or .tsx) as well as my tests. For a long time, I positioned my tests files as a sibling of the source folder, but having them close to the files they are testing is a way to keep them in sight. Because they are always in view, I tend to test more. I also clearly see if a file is not having a test file.

Some types are cross domains. Shared types are also valid for very generic visual components. In that case, I have at the root, inside the source folder a domain called “shared.” The cross-domain folder is the one that every domain folder can access. Having a shared folder require to be diligent. It is easy to insert code random code instead of thinking where to locate the file accurately.

If we come back to the type, each domain folder has a model folder which has many files. The separation is not one type, one file. The reason is that it would become uncontrollable. The number of types grows very fast, and it is not rare to have thousands of types, even for a small product. The idea is to divide the file per main entity. For example, a product (interface Product) can have a product category (Interface ProductCategory) and a ProductSize (enum ProductSize). These three types can be in the “Product.ts” file. Again, there is room for subjectivity. Someone could argue that more or less type can be in or out of a file. The important here is to have something that makes sense. I often like to have the main entity, in that case, “Product” to hold every children class, interface, enum, type in the same file. I like having a mapping file “ProductMapping.ts” that manipulate the entity from a normalized structure to a denormalized for example.

At the end of the day, the most important detail is to stay coherent. The overall goal is to find where are a type without searching for a long time.

TypeScript and React to Animate a Custom HTML Bar Graph

In my work at Netflix, I had to create a page to visualize when a cache (also known as an appliance) can receive new movies. The former Partner Portal had a table with one row per cache for a specific organization. Every row had one column for every hour of the day (24 columns). The table can be very verbose depending on how structured an organization is in term of sites and appliances. I opted to an improved visualization that removed the redundancy of the unused cells and leveraged React and animation to have the user following the transformation when changing options like timezone and visualization preferences. The result is that a user interfaces less clunky that displays four times more information for the same viewport.

Cache Fill Window

I decided to design a simplistic user interface. The top row of the section is what the user can configure for the chart. The first selector allows choosing from a limited set of timezone available from the organization’ sites. The second selection is how caches are sorted. Underneath is the result. You can see the actual time with the “now” pin and the hour used that are highlighted. This is a small detail that fades away most of the hours of the day instead of having a dedicated column as in the previous design.

I opted to remove the redundancy of repeating the hours on every row. The original design has on top of each appliance a row with 24 columns for each hour of the day. It was taxing the screen with redundant information and it was taking space were pertinent information can be positioned. The change lights up the readability but also give more room for useful data. To help the user having a clear idea of the time, I drop a line from the used hour down to the bottom of the page. Also, when the user hovers a cache, I have a popover that mentioned the time frame.

In term of navigability, it is possible to click on any cache to move to the detail page of this one. The green handle shows the manifest cluster of the caches. It has multiple goals. The first one is to show the name of the manifest cluster. The second is to indicate if the caches type (manifest cluster, global, flash). The third is for the future when we add the feature to allow the user to alter the time from a manifest cluster — the green handle will be an actual drag-and-drop handle.

So, how it was built? All with TypeScript, React and HTML/CSS. The first row of option has its own component and the result has also its own component. Both live in the “FillWindows” component.

React Components for Fill Windows Feature

The menu is simple and has two functions in its props which allows the “Fillwindows.tsx” to know how to render the information.  The “FillwindowsNowIndicator” is the pin that point the current time. It receives the timezone as well as some detail about the width of the diagram. Finally, depending on the organization, a different number of “FillwindowsCluster” are generated. Information travels always from the “Fillwindows.tsx” which has the main DIV with a position absolute. The position type to absolute is required to position every element with a left and top style which will be animated later by setting the value and animating everything with a translation.

The “Fillwindows.tsx” is rendering the vertical bar as well but this could be extracted into another component as well. The separation into an additional component is a future improvement I plan to execute. However, at the moment, it works flawlessly by having the “Fillwindows.tsx” knowing about the business models object that has the information about the caches. With the information, it is possible to figure out which hours to highlight and which one to draw.

The graph is horizontally centered as well as being absolute. It is centered allowing a variety of resolution to have a look and feel similar. The configuration is written in the CSS file of the main component. The reason is that it will not change dynamically, hence can set it outside React.

.FillWindows .timeline-container{
    position: absolute;
    left: 0;
    right: 0;
    margin-left: auto;
    margin-right: auto;
}

Most of the feat of this feature is how to get the right position for every element. The calculation is performed at the “Fillwindows.tsx” render’s level where the width and height of the whole graph can be calculated with the business models. From the main component, the right final position of every element can be passed down in all children component by properties. For example, the “FillwindowsCluster.tsx” is receiving a top and a left position and also receive the height of each appliance they must render.

const individualClusters: JSX.Element[] = [];
let top = tableHeader;
clusters.clusters.forEach((cluster: FillWindowsDataCluster) => {
    individualClusters.push(
        <FillWindowsCluster
            key={"fwc-" + cluster.clusterId}
            cluster={cluster}
            top={top}
            columnWidth={columnWidth}
            applianceHeight={applianceHeight}
        />);
    top += cluster.numberOfAppliances * applianceHeight + spaceBetweenCluster;
});

return <div
    className="clusters"
    style={
        {
            width: totalClustersWidth
        }
    }
>
    {individualClusters}
</div >;

The animation is using the React and animation technic previous discussed. For each element, it sets the top and left of the final position and rewind with the previous position with CSS animation that has a transition. It means the “FillwindowsCluster.tsx” has in its class the two values as well as a reference to the DOM element to modify the style dynamically.

private domCluster: HTMLDivElement | null = null;
private lastLeftPosition: number = 0;
private lastTopPosition: number = 0;

The React receive property function get the current position.

public componentWillReceiveProps(nextProps: FillWindowsClusterProps): void {
    if (this.domCluster !== null) {
        const coord = this.domCluster.getBoundingClientRect();
        this.lastLeftPosition = coord.left;
        this.lastTopPosition = coord.top;
    }
}

And the React did update function calculate the animation values, moving immediately the position to its last position relatively to the final position and using the request animation frame to tell the browser to remove the transformation (delta between last and current position).

public componentDidUpdate(previousProps: FillWindowsClusterProps): void {
    if (this.domCluster !== null) {
        const coord = this.domCluster.getBoundingClientRect();
        const deltaPositionLeft = this.lastLeftPosition - coord.left;
        const deltaPositionTop = this.lastTopPosition - coord.top;
        if (this.domCluster !== null) {
            this.domCluster.style.transform = `translate(${deltaPositionLeft}px, ${deltaPositionTop}px)`;
            this.domCluster.style.transition = "transform 0s";
        }
        requestAnimationFrame(() => {
            if (this.domCluster !== null) {
                this.domCluster.style.opacity = "1";
                this.domCluster.style.transform = "";
                this.domCluster.style.transition = "transform 850ms, opacity 800ms";
            }
        });
    }
}

If this is not clear, please refer to the link previous mentioned in this article.

The re-design of the feature could have been the same old static grid with a huge repetition of “hours” and several cells empty. However, with a little bit of design, something more refines was born. The touch of animation improves the user experience while adding a finishing touch.

My Second TypeScript Book is Available

You read right! My second TypeScript book! I published my first book entitled Holistic TypeScript in April this year and wrote about my motivation in a blog post. This time, the publisher Packt reached for a quick start guide for TypeScript 3.0.

I jumped at the opportunity to cover all feature in a simpler way than my original book. While the former book is up-to-date with all TypeScript’s features in a great depth, the latter is targeting introducing all powerful feature of the language.

The book is available on Packt website and on Amazon.

In this book you will learn how to:

  • Set up the environment quickly to get started with TypeScript
  • Configure TypeScript with essential configurations that run along your code
  • Structure the code using Types and Interfaces to create objects
  • Demonstrate how to create object-oriented code with TypeScript
  • Abstract code with generics to make the code more reusable
  • Transform the actual JavaScript code to be compatible with TypeScript

I encourage you to read TypeScript 3.0 Quick Start Guide if you are new to TypeScript or if you want to share your love of TypeScript to a friend that is not yet leveraging the power of type for web development. For those at an intermediary level and higher, Holistic TypeScript remains the best choice even if it cover up to 2.8. I’ll update Holistic TypeScript every year with new TypeScript features. 

Detecting a New Version of your React/Redux App in 15 minutes

While I am well aware of the feature of notifying to the user that a new version is ready to be served, I never implemented a solution myself. Gmail and many websites do it to allow the user to refresh the website which brings the new JavaScript, CSS and other assets. It is a great way to encourage users to refresh the page once in a while. With Web application, it occurs that some users do not refresh so often. Myself, I rarely refresh my Gmail webpage until I see the notification.

This week, someone raised the point that it would be interesting to have this feature on the application I am working on at Netflix. I wish I had time to do it, but instead of procrastinating, I decided to give it a try. The idea was to implement a way as cheap as possible since I have a backlog that is gargantuan

If you recall, a few days ago, I discussed how to burn the Git hash into your React application. The article described how to inject in the environment variable the Git hash of the actual build. It is done at compilation time and the React has a way to read the information from JavaScript. In my case, the version is stored in an environment variable named “REACT.APP_VERSION.” It is accessible at runtime. That being said, the version remains on the client browser until the user fetches the new JavaScript file that has a new value which happens only on a new build. The idea is to leverage the fact that if the client keeps the version until a new version is available, on a refresh, then checking once in a while for a version change is a matter of comparing the Git hash on the client machine to the actual head of the repository.

The idea can be broke down in few steps:

  1. On build, burn the Git Hash into the JavaScript
  2. On build, generate a file with the Git Hash
  3. Fetch once in a while from the server a file that has the latest Git
  4. If the Git Hash from the JavaScript environment variable is different from the file on the server, show a message to the user to refresh

The first step has been already discussed, but in short, it consists to change the “npm run build” to take the head Git hash and to pass it down to React.

 "build": "REACT_APP_VERSION=$(git rev-parse --short HEAD) react-scripts-ts build"

The second step require a change on the build system. At Netflix, we are using Jenkins. I added a Bash Script step that look like the following:

CommitHash=$(git rev-parse --short HEAD)
echo "HASH"
echo $CommitHash
echo $CommitHash > "public/version.json"
echo "VERSION FILE BEGIN"
cat public/version.json
echo "VERSION FILE END"

The step number is open to how you want to handle it. I personally want to avoid setTimout. I rather have a Redux Middleware that will check once in a while. The middleware holds the time of the last check and on every action, verify that the time has elapsed from the threshold that you set. I have mine to 5 minutes. Every 5 minutes, or more depending of when the user does an action, it fetches the static file. As you can see in the previous step, the Git Hash is stored in a file under the “public” folder which is accessible with a simple Ajax call. If the string is different from the JavaScript environment variable, an action is dispatched that shows a message to the user to refresh the page.

const diff = this.currentTimeSinceEpoch() - this.lastCheck;
if (diff > SECONDS_BETWEEN_VERSION_CHECK) {
    this.lastCheck = this.currentTimeSinceEpoch();
    (async () => {
        const currentVersion = process.env.REACT_APP_VERSION === undefined ? "dev" : process.env.REACT_APP_VERSION;
        try {
            const file = await AjaxLibraryThatYouUse<string>({
                request: {
                    url: "/version.json"
                }
            });
            const newVersion = file.result;
            if (newVersion !== currentVersion) {               next(SharedActions.actionInfoMessage(localize(globalResources.new_version_available)));
            }
        } catch (error) {
           // Track error here
        }
    })();
}

The solution took less than writing this article! It might not be a push notification, neither having a complete Rest API. It is not the most elegant because we fetch every 5 minutes, but at the end of the day, a new feature is born in 15 minutes of work. Now, I’m back to my backlog!

Handling Unexpected Error with React and Redux

Regardless of how professional developer you are, there always will be an exception that will slip between your fingers, or should I say between your lines of code. These errors that bubble up the stack are called unexpected error. While it is always preferable to catch the error as close as possible of where the exception is thrown, it is still better to catch them at a high level. In the web world, it gives an opportunity to have a generic message to the user gracefully. It also provides an open door to collect the unexpected error and act before having any of your customers reach you.

There are three places where you need to handle unexpected errors in a stack using React and Redux. The first one is at React level. An unexpected error can occur in a render method for example. The second level is during the mapping between Redux and React. The error occurs when we move data from the Redux’s store to the React’s property of the connected component. The third level is an error in the chain of middlewares. The last one will bubble up through the stack of middleware and explode where the action was dispatched. Let’s see how we can handle these three cases in your application.

React Unhandled Exception

Since version 16, React simplified the capture of error by introducing the lifecycle function “componentDidCatch.” It is a function like “render” or “componentShouldUpdate” that come with the framework. The “componentDidCatch” is triggered when an exception go thrown any children of the component. The detail about what it covers is crucial. You must have a component that englobes most of your application. If you are using React-Router and would like to keep the web application with the same URL and have the menus to stay in place, this can be tricky. The idea is to create a new component with the sole purpose of wrapping all top route components. Having a single component to handle the unexpected error is interesting. It is simple, easy to test, with a cohesive and single task.

export interface ErrorBoundaryStates {
  hasError: boolean;
}
export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryStates> {
  constructor(props: ErrorBoundaryProps) {
    super(props);
    this.state = { hasError: false };
  }

  public componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
    this.setState({ hasError: true });
    YourLoggingSystem.track(error, "ErrorBoundary", { errorInfo: errorInfo });
  }

  public render() {
    if (this.state.hasError) {
      return <div className="ErrorBoundary">
      The application crashed. Sorry!
      </div>;
    }
    return this.props.children;
  }
}

However, with React-Router, every route is assigned as property. The property is an excellent opportunity to create a function that returns the React class.

// CODE IN YOUR TOP APP CONTAINER:

// Constructor:
 this.page1Component = withErrorBoundary()(Page1Component));
// Render:
<Route path={Routes.PAGE_1} component={this.page1Component} />

// UTILITY FUNCTION
export const withErrorBoundary = () => <P extends object>(Component: React.ComponentType<P>) =>
  class WithErrorBoundary extends React.Component<P> {
    render() {
      return <ErrorBoundary}><Component {...this.props} /></ErrorBoundary>;
    }
  };

Redux Mapping Unhandled Exception

This section will be short because it is covered with React. However, I wanted to clarify that this can be tricky if you are not doing exactly like the pattern I described. For instance, if you are wrapping the “withErrorBoundary” not at the initialization of the route but directly when you connect — it will not work. For example, the code below does not work as you might expect. The reason is that the error is bound to the component but not to the code being bound by the React-Connect.

export default connect<ModelPage1, DispatchPage1, {}, {}, AppReduxState>(
    (s) => orgMappers.mapStateToProps(s),
    (s) => orgMappers.mapDispatchToProps(s)
)(WithErrorBoundary()(Page1Component));

Outside of the initial solution proposed, it is also valid to wrap the “connect” to have the desired effect of receiving the error in the “componentDidCatch” of the “ErrorBoundary”. I prefer the former solution because it does not coerce the ErrorBoundary with the component forever.

export default WithErrorBoundary(connect<ModelPage1, DispatchPage1, {}, {}, AppReduxState>(
    (s) => orgMappers.mapStateToProps(s),
    (s) => orgMappers.mapDispatchToProps(s)
)(Page1Component));

Redux Middleware Unhandled Exception

The last portion of the code that needs to have a catch-all is the middleware. The solution goes with the Redux’s middleware concept which is to leverage function that calls themselves. The idea is to have one of the first function, middleware, to be a big try-catch.

const appliedMiddleware = applyMiddleware(
  thunk,                       
  unhandledExceptionMiddleware,  
  middleware1,      
  middleware2, 
  middleware3, 
  middleware4         
);

// Excerpt of the middleware:
return (api: MiddlewareAPI<Dispatch, AppReduxState>) =>
       (next: Dispatch) =>
       (action: Actions): any => {
            try {
                return next(action);
            } catch (error) {
                YourLoggingSystem.track(error, "Unhandled Exception in Middleware");
                return next(/*Insert here an action that will render something to the UI to indicate to the user that an error occured*/);
            }
 };

Summary

Handling errors in a React and Redux world require code to be in a particular way. At this day, the documentation is not very clear. Mostly because there is a clear separation between React, Redux, Redux-Connect, and React-Router. While it is very powerful to have each element of the puzzle separated, this comes with the price that the integration is in a gray area. Hopefully, this article uncovers some mystery around how to collection unhandled errors and removed confusion with the particular case of why mapping error can throw error through the React mechanism when not positioned at the right place.