Async Prop Fetching
How to move dependency resolving into your routes
Props on “views”
In most vue applications my “views” are distinct from the rest of my components. Not only are they stored in a separate folder, but they never have props. Instead, the expectation is that anything dynamic about the component is likely to be driven by the route.
For example, let’s assume we had a component that takes an id
prop to fetch a User
.
const props = defineProps<{
id: string,
}>()
const { id } = toRefs(props)
const user = userStore.getById(id)
If that component were a view, it would expect to find the id
in route params.
const route = useRoute()
const id = computed(() => route.params.id)
const user = userStore.getById(id)
This is important because we don’t have a good opportunity to supply props to our component since it’s automatically mounted by RouterView.
Accessing params from route
Alternatively, if you’re using vue-router you can bind all the route params to the component automatically with the route.props attribute. However, this is NOT type safe.
With Kitbag Router the props attribute offers even more!
- Correct types on the route params. The params passed to your callback has all of the type context including params from parents and any defaults applied.
- Correct type for return type. Your callback will throw a Typescript error if it returns anything other than the type defined by the component for props.
- Support for async prop fetching. By supporting promises, you can do much more than just forward values from params or insert static values.
Resolving dependency from route param
We think this callback layer for props in your routes has the possibility to redefine how we think about resolving dependencies.
In the examples above the components ultimately depend on a User
dependency. They are provided an id
and the logic for resolving the dependency falls on the component.
Now you have the option of encapsulating this responsibility in the route.
import { defineRoute } from '@kitbag/router'
import { defineAsyncComponent } from 'vue'
import UserView from '../components/UserView.vue'
const route = defineRoute({
name: 'user',
path: 'user/[id]',
component: UserView,
props: async (({ id }) => {
const user = await userStore.getById(id)
return { user }
})
})
Now your components can just expect the dependency
const props = defineProps<{
user: User,
}>()
Async props and suspense
When your props are async the component you provide gets wrapped in vue’s defineAsyncComponent
utility. Async components require using <suspense>
. Read more about suspense in vue’s documentation.
Type safety
Regardless of your preferred approach for resolving dependencies, Kitbag Router’s type safety on props will still probably save you from runtime errors. Any routes with components with required props will now be required to assign those props in the route.props
callback.
TLDR
Kitbag Router (v0.7) now has props
attribute on routes! If you’ve used vue-router you know how useful it is to forward props from route params. What Kitbag Router adds is type safety and promises! Now you can fetch your async data with route params and provide that down to your components.
We think this paradigm is super interesting and even cooler is what it enables us to do in the future.
Check out our docs
https://router.kitbag.dev
Give us a star ⭐️
github.com/kitbagjs/router
Happy engineering!