Tungsten

Data Loading

Web pages frequently display data from a back-end service. In Tungsten, the data to be loaded is normally specified within the route, and is loading during routing.

// routes.tsx
type News = {
title: string
content: string
}
export const routes = {
'/': {
data: () => fetch('/latest-news'),
content: (latestNews) => <Home latestNews={latestNews} />
} satisfies<Params<never>, News[]>
} as const satisfies AppRoutes

Here we fetch some news for the homepage from <ourSite>/latest-news, and we pass a function as content which accepts the data as the first argument.

Unfortunately TypeScript doesn't give very good control of lists of items of generic types. We need to use a type like AppRoute<any, any> within our Routes list to allow for routes with any possible Param and Data types, but the any type disables type checking, and so actually disables the type safety we should have here (if anyone knows of a solution to this please let me know). To get around the issue we specify the type of the current route explicity with satisfies<Params<never>, News[]>, restoring type safety.

Any route parameters are available to the data function as the first argument

// routes.tsx
export const routes = {
'/users/:id': {
data: ({ id }) => fetch('/user/' + id),
content: (user) => <Home user={user} />
} satisfies<ParamsFromPath<'/users/:id'>, User>
} as const satisfies AppRoutes

Global data

Sometimes you just want to load some data on every page. You can do this with globalData

import { globalData } from 'tungsten'
declare module 'tungsten' {
interface GlobalData {
userId: number
}
}
globalData( () => fetch('/global-data') )

globalData simply takes a function to load data. The declare code lets us specify the type of data this will return, so that when we retrieve the data later, it is correctly typed.

The global data is then available on the instance of Tungsten components

class Page extends SimpleComponent {
content = () => (
<div>User ID is: {this.__instance.globalData.userId}</div>
)
}