Context
Context is a primitive object which let's you pass data from middleware or layout, to the targeted route.
Context in layouts
Imagine a scenario, where you have a layout with navbar, in which you want to show a very small picture of a currently logged user. No problem, you can just easily fetch user data from Database, and show it. However, what if you want to display some information about the user in a currently displayed page ? Do you have to fetch user data again ? Well thanks to the context, you don't have to.
Here is an example of using ctx in middleware:
/**@jsx h */
/**@jsxFrag Fragment */
import { serve } from 'https://deno.land/std/http/server.ts'
import { createHandler, withLayout, Props, h, Fragment } from 'https://deno.land/x/atlet@1.2.0/mod.ts'
import { getTheoreticallyAuthorizedUser } from 'legit-auth'
type Context = {
user: {
id: string
name: string
}
}
const Layout = async (props: Props<Context>) => {
props.ctx.user = await getTheoreticallyAuthorizedUser(props.request)
return (
<main>
<nav>
<img src={props.ctx.user.picture} alt="Your profile picture" />
</nav>
<section>{props.children}</section>
</main>
)
}
const Home = withLayout(Layout, (props: Props<Context>) => (
<h1>Hello {props.ctx.user.name}</h1>
))
const handler = await createHandler({
'/': Home,
})
// you can also use Deno.serve which is available in Deno 1.35
serve(handler)Context in middleware
Example of using ctx in middleware:
/**@jsx h */
/**@jsxFrag Fragment */
import { serve } from 'https://deno.land/std/http/server.ts'
import { createHandler, MIDDLEWARE, Props, h, Fragment } from 'https://deno.land/x/atlet@1.2.0/mod.ts'
import { getTheoreticallyAuthorizedUser } from 'legit-auth'
type Context = {
user: {
id: string
name: string
}
}
// You can also pass the type into the createHandler function itself
const handler = await createHandler<Context>({
// No need to define Props type, since it's generic version is inferred
[MIDDLEWARE]: (props) => {
// TypeScript IntelliSense will work here 😎
props.ctx.user = await getTheoreticallyAuthorizedUser(props.request)
},
'/': (props) => (
<h1>Logged in as {props.ctx.user.name}</h1>
)
})
// you can also use Deno.serve which is available in Deno 1.35
serve(handler)Unfortunately, if you want to have your route functions in different files, the inference will break. In that case, you can export your type which defines the data in your ctx, and pass it as a generic type to the props type. This also applies for using ctx in layouts.
/**@jsx h */
/**@jsxFrag Fragment */
import { serve } from 'https://deno.land/std/http/server.ts'
import { createHandler, MIDDLEWARE, Props, h, Fragment } from 'https://deno.land/x/atlet@1.2.0/mod.ts'
import Home from './Home.tsx'
export type Context = {
user: {
id: string
name: string
}
}
const handler = await createHandler<Context>({
[MIDDLEWARE]: (props) => {
props.ctx.user = await getTheoreticallyAuthorizedUser(props.request)
},
'/': Home,
})
// you can also use Deno.serve which is available in Deno 1.35
serve(handler)/**@jsx h */
/**@jsxFrag Fragment */
import { Props, h, Fragment } from 'https://deno.land/x/atlet@1.2.0/mod.ts'
import { Context } from './main.tsx'
export default function Home(props: Props<Context>) {
return (
// Autocompletion will work here (hopefully)
<h1>Logged in as {props.ctx.user.name}</h1>
)
}