Skip to content

[SDK] Hooks

FTCHD edited this page Sep 6, 2024 · 5 revisions

⚠️ 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.

useFarcasterId

This hooks returns the Farcaster ID of the current logged in user on FrameTrain.

Example

import { useFarcasterId } from '@sdk/hooks'

export default function Inspector() {
	const fid = useFarcasterId()
}

useFarcasterName

This hooks returns the Farcaster username (fname) of the current logged in user on FrameTrain.

Example

import { useFarcasterName } from '@sdk/hooks'

export default function Inspector() {
	const fid = useFarcasterName()
}

useFrameId

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.

Example

import { useFrameId } from '@sdk/hooks'

export default function Inspector() {
	const frameId = useFrameId()
}

useFrameConfig

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.

Example

import { useFrameConfig } from '@sdk/hooks'
import type { Config } from '.'

export default function Inspector() {
	const [config, updateConfig] = useFrameConfig<Config>()
}

useFrameStorage

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.

Example

import { useFrameStorage } from '@sdk/hooks'
import type { Config } from '.'

export default function Inspector() {
	const storage = useFrameStorage()
}

useUploadImage

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.

Example

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>
	)
}

useFramePreview and resetFramePreview

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: use-frame-preview

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.

Example

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>
	)
}