-
-
Notifications
You must be signed in to change notification settings - Fork 30
[SDK] Hooks
⚠️ Note: Do not import any hooks that are not in the @/sdk/hooks
folder. This does not refer to your own hooks that you create in your template folder.
FrameTrain provides a number of useful hooks that you can use immediately. Use these hooks inside your Inspector to build complex interactions inside your template.
This hooks returns the Farcaster ID of the current logged in user on FrameTrain.
import { useFarcasterId } from '@sdk/hooks'
export default function Inspector() {
const fid = useFarcasterId()
}
This hooks returns the Farcaster username (fname
) of the current logged in user on FrameTrain.
import { useFarcasterName } from '@sdk/hooks'
export default function Inspector() {
const fid = useFarcasterName()
}
This hooks returns the current Frame ID. You can use it to identify the current Frame, which is useful for certain actions like Image Uploading.
import { useFrameId } from '@sdk/hooks'
export default function Inspector() {
const frameId = useFrameId()
}
Returns the current Frame configuration and a function to update it. You can pass it your Config
as generic type in order to have proper IDE completion.
The updateConfig
function is debounced internally to prevent unnecessary changes.
When updateConfig
is called, all other keys/values currently in it are preserved, this means you only have to pass it the keys that you want to change, not the entire config.
import { useFrameConfig } from '@sdk/hooks'
import type { Config } from '.'
export default function Inspector() {
const [config, updateConfig] = useFrameConfig<Config>()
}
Returns the current Frame storage. This is useful to parse and show the contents of the storage, for example to show the submissions of a Form.
import { useFrameStorage } from '@sdk/hooks'
import type { Config } from '.'
export default function Inspector() {
const storage = useFrameStorage()
}
Not everything can be rendered dynamically. In most use-cases you will want to give the user the option to upload an image.
Receives a Buffer
or base64
string and a contentType
, and uploads the image. Returns a promise that resolves to the fileName
and filePath
of the uploaded image.
Uploaded images can be used however you like in your template, for example to display a background or slideshow.
To get the full URL and display any uploaded image in an <img>
element or otherwise, concatenate the filePath
with the base process.env.NEXT_PUBLIC_CDN_HOST
.
import { useUploadImage } from '@sdk/hooks'
import { useState } from 'react'
export default function Inspector() {
const uploadImage = useUploadImage()
const [imagePath, setImagePath] = useState('')
return (
<div className="flex flex-col gap-2 ">
<h2 className="text-lg font-semibold">Background Color</h2>
<ColorPicker
uploadBackground={async (base64String, contentType) => {
const { filePath, fileName } = await uploadImage({
base64String: base64String,
contentType: contentType,
})
setImagePath(filePath) // usually you'd want to update the frame config
return filePath
}}
/>
{imagePath && (
<img src={`${process.env.NEXT_PUBLIC_CDN_HOST}/${imagePath}`} />
)}
</div>
)
}
These two hooks allow you to control the left side of the editor, namely the preview panel.
The Preview panel updates automatically when the Frame configuration changes, but it does so without navigating back to the initial slide.
This is the normal behavior and the one the user expects. Say you're the user now, and creating a Frame using the Form template on FrameTrain. When you edit the 3rd Slide's backgroundColor
you want the preview panel to update without navigating away from the slide.
As noted before, this is the expected behavior, but it's important to understand how it works, to better understand how and when to control it yourself. The preview panel stores the current handler
name, the buttonIndex
that was pressed, the inputText
that was present, and the params
that were passed in the URL. When the Frame configuration changes, the preview replays call to your handler using the data it stored. This way the preview refreshes without changing what slide you were on.
In some cases however, you want to control the preview panel yourself. Let's say you're creating a template that has multiple slides that the User can edit (like the Presentation template). In your Inspector, you let the user choose which slide they want to edit. The interesting part comes now, you can use the useFramePreview
hook to control the preview panel so it changes to the selected slide as well.
So when the user clicks in the Inspector the preview changes as well, the behavior looks something like this:
If you want to reset the preview panel, you can use the resetFramePreview
hook. This hook returns a single function that you can call to reset the preview panel to the initial state.
import { useFramePreview } from '@sdk/hooks'
import { useState } from 'react'
export default function Inspector() {
const [previewData, setFramePreview] = useFramePreview()
return (
<div className="flex flex-col gap-2 ">
<h2 className="text-lg font-semibold">Slides</h2>
{config.slides?.map((slide: Slide, i: number) => {
return (
// This is your Slide
<div key={i} onClick={() => {
// Do your logic like `changeSlideIndex` to update the active slide in your Inspector.
// Now comes the important part, you use the useFramePreview hook to control the preview panel:
setFramePreview({
handler: 'page',
buttonIndex: 1,
inputText: '',
)}
}} />
)}
)}
</div>
)
}