Fragment
There are two ways to use fragments in Houdini. The first is defining it inside of the useFragment hook and this
approach will always work in all situations:
import { graphql, useFragment } from "$houdini";
export function ShowCard(props: { show: ShowCardInfo }) { const data = useFragment(props.show, graphql(` fragment ShowCardInfo on Show { name } `))
return ( <div> {data.name} </div> )}And then can be passed to your graphql query:
query ShowInfo($id: ID!) { show(id: $id) { ...ShowCardInfo }}And then threaded through to the component:
import { ShowCard } from '...'import type { PageProps } from './$types'
export default function ShowInfoView({ ShowInfo }:PageProps) { return ( <ShowCard show={ShowInfo.show} /> )}import { ShowCard } from '...'
export default function ShowInfoView({ ShowInfo }) { return (<ShowCard show={ShowInfo.show}/>)}Component Fields
When building reusable components, it is very common to find yourself repeatedly importing the same component and mixing in the same fragment over and over. This can get really tedious and so Houdini tries to address this by blurring the lines between your queries and your component library.
The idea is pretty simple on the surface: components can register themselves as fields on a type. But
before we can use this feature, we need to enable the feature flag in houdini.config.js. Keep in mind this
means that this API might change with any minor version. We understand this isn’t semantic versioning by the book
but hopefully you understand.
export default { // ... features: { componentFields: true }}With that enabled, your components can define fragments using a slightly different API:
import { GraphQL } from '$houdini'
type Props = { user: GraphQL<`{ ... on User @componentField(field: "Avatar") { avatarURL } }`>}
export default function UserAvatar({ user } : Props) { return <img src={user.avatarURL} />}import { graphql } from '$houdini'
graphql(`{ ... on User @componentField(field: "Avatar", prop: "user") { avatarURL }}`)
export default function UserAvatar({ user } : Props) { return <img src={user.avatarURL} />}This example registers the Avatar field on the User type:
query Profile { currentUser { Avatar }}Which can be used directly as a component in your page source. Notice there’s no need to import the component or remember the name of the prop that needs to be passed:
import type { PageProps } from './$types'
export default function ShowInfoView({ Profile }: PageProps) { return ( <div> <Profile.currentUser.Avatar /> </div> )}export default function ShowInfoView({ Profile }) { return ( <div> <Profile.currentUser.Avatar /> </div> )}Component Field Arguments
@componentField can be mixed with @arguments to define arguments on the field added for the component:
import { GraphQL } from '$houdini'
type Props = { user: GraphQL<`{ ... on User @componentField(field: "Avatar") @arguments(size: { type: "Int" }) { avatarURL(size: $size) } }`>}
export default function UserAvatar({ user } : Props) { return <img src={user.avatarURL} />}import { graphql } from '$houdini'
graphql(`{ ... on User @componentField(field: "Avatar") @arguments(size: { type: "Int" }) { avatarURL(size: $size) }}`)
export default function UserAvatar({ user } : Props) { return <img src={user.avatarURL} />}query Profile { currentUser { Avatar(size: 150) }}Named Exports
If your file exports the component by a specific name (instead of a default export) then you must tell houdini which export it should use:
import { GraphQL } from '$houdini'
type Props = { user: GraphQL<`{ ... on User @componentField(field: "Avatar", export: "UserAvatar" ) { avatarURL(size: $size) } }`>}
export function UserAvatar({ user } : Props) { return <img src={user.avatarURL} />}import { graphql } from '$houdini'
graphql(`{ ... on User @componentField(field: "Avatar", export: "UserAvatar" ) { avatarURL(size: $size) }}`)
export function UserAvatar({ user } : Props) { return <img src={user.avatarURL} />}