AsMatch shows different HTML based on a simple rule, like a traffic light. Anywhere a ternary is used, AsMatch can be used, yet more concise, easy to work on, simple to read.


Vanilla Ternary

<div>
{
products.as === 'loading' ?
<>Products started loading {relTime(products.began)}</> :
products.as === 'error' ?
<>Error while loading products: {products.error}</> :
products.as === 'success' ?
<ProductList items={products.results} /> : null
}
</div>

AsMatch JSX

<div>
<AsMatch over={products} match={{
loading: x => <>Products started loading {relTime(x.began)}</>,
error: x => <>Error while loading products {x.error}</>,
success: x => <ProductList items={x.results} />
}} />
</div>

Explain AsMatch Quicky


The AsMatch component takes two props: over, match. The over prop is the object being checked, the match prop are the handlers for each value of over.as. If over.as can be the string loggedIn, the match object needs it too. its value is a function that renders the appropriate JSX. When finally run, only one function is rendered at a time. Exactly based on the current value of over.as.

In "AsMatch Example," the value of products.as could be loading or error or success. Therefore the match object had functions for each. When run, the code would first show the JSX from the function for loading, afterward success or perhaps error.

What Can Be Matched On?

  1. The over prop is an object.
  2. It always has .as property.
  3. as is a string.

The string tells the object's state. These rules are followed perfectly by these examples.

A List Result

var error = { as: "error", error: "An error occurred" }
var success = { as: "success", count: 170, items: [......] }

A Tab or Page System

var currentTab = { as: "account", userId: "4021-6as" }
var currentTab = { as: "dashboard", dashboardData: {.......} }
var currentTab = { as: "products", products: {as: 'loading'} }

A Log In System

console.log(loginState) // { as: "loggedIn", jwt: token }
await userActions.logout()
console.log(loginState) // { as: "unAuth" }

Example in TypeScript

type Auth = { as: "unAuth" } | { as: "loggedIn", jwt: Token }
type Tab =
| { as: "account", userId: string }
| { as: "dashboard", dashboardData: DashboardInfo }
| { as: "products", products: ListResult<Product> }
type ListResult<T> =
| { as: "error", error: string }
| { as: "loading", began: number }
| { as: "success", items: T[], count: number }

Since AsMatch has TS in mind, each condition in the match props is automatically known to TypeScript as soon as the over prop is added. The conditions in match only see the properties specifically in its type. For the Tab example, only in the function handling account is userId: string shown.


Using The Match Handlers


<div>
<AsMatch over={products} match={{
loading: x => <>Products started loading {relTime(x.began)}</>,
error: x => <>Error while loading products {x.error}</>,
success: x => <ProductList items={x.results} />
}} />
</div>

Seen earlier, the match object had three handlers: one for loading, one for error, and one for success. Each takes a single parameter, whatever was passed into the over prop. Because the number of handlers depends on the possible values of over.as, three handlers are required above.

<div>
<AsMatch over={loginState} match={{
unAuth: x => <button>Login</button>,
loggedIn: x => <button>Log out of {getOwnName(x.token)}</button>,
}} />
</div>

Each handler function receives exactly the object that matched their key. For example, in the loggedIn handler, the function receives an object with the property .token. In unAuth, it does not. These objects are different because each handler corresponds to a specific state of the loginState object passed to over.

TypeScript Match Prop Autocomplete

The match object always stays in sync with the possible states of over.as. If the type of over changes or new states are introduced, the AsMatch component will alert TS to places missing functions to handle all the cases of over.


          ┌─────────┐ 
          │ AsMatch │ 
          └────┬────┘ 
               │         ┌──────┐      ┌───────┐
               │         │ over │      │ match │
               │         └───┬──┘      └───┬───┘
               │             │             │    
               │             │             │             ┌───────┐
               └────────────►│────────────►│────────────►|  JSX  |    
                             │             │             └───────┘
                             │             │ 
                         ┌───┴──┐      ┌───┴───┐
                         └──────┘      └───────┘


How To Use VarSet
ArkSouthern

AuthoredMar 28th 2024
UpdatedSep 27th 2024
IDn-hw-avx