Skip to main content
React hooks for saving, fetching, and deleting goal templates that can be reused to create new goals.

useTemplates

Fetch all goal templates for the current user.
const { data, isLoading, error } = useTemplates()

Returns

data
GoalTemplate[]
Array of goal templates, ordered by creation date (newest first)
isLoading
boolean
Loading state of the query
error
Error | null
Error object if the query failed

Example

import { useTemplates } from '@features/goals/api/use-templates'

function TemplatesList() {
  const { data: templates, isLoading } = useTemplates()
  
  if (isLoading) return <div>Loading templates...</div>
  
  return (
    <ul>
      {templates?.map((template) => (
        <li key={template.id}>
          {template.name}
        </li>
      ))}
    </ul>
  )
}

useSaveTemplate

Save a goal as a reusable template.
const { mutate, mutateAsync, isPending } = useSaveTemplate()

Returns

mutate
(params: SaveTemplateParams) => void
Function to save a template
mutateAsync
(params: SaveTemplateParams) => Promise<GoalTemplate>
Async function to save a template and await the result
isPending
boolean
Loading state of the mutation

Parameters

name
string
required
The name of the template
goal
Partial<Goal>
required
The goal structure to save as a template. Typically includes fields like title, description, end_date, and any sub-goals.

Example

import { useSaveTemplate } from '@features/goals/api/use-templates'
import { useGoal } from '@features/goals/api/use-goals'

function SaveAsTemplateButton({ goalId }: { goalId: string }) {
  const { data: goal } = useGoal(goalId)
  const { mutate: saveTemplate, isPending } = useSaveTemplate()
  
  const handleSave = () => {
    const name = prompt('Enter template name:')
    if (!name || !goal) return
    
    saveTemplate({
      name,
      goal: {
        title: goal.title,
        description: goal.description,
        end_date: goal.end_date,
        // Include any other fields you want in the template
      },
    })
  }
  
  return (
    <button onClick={handleSave} disabled={isPending}>
      Save as Template
    </button>
  )
}

useDeleteTemplate

Delete a goal template.
const { mutate, mutateAsync, isPending } = useDeleteTemplate()

Returns

mutate
(templateId: string) => void
Function to delete a template
mutateAsync
(templateId: string) => Promise<void>
Async function to delete a template and await completion
isPending
boolean
Loading state of the mutation

Parameters

templateId
string
required
The ID of the template to delete

Example

import { useDeleteTemplate } from '@features/goals/api/use-templates'

function DeleteTemplateButton({ templateId }: { templateId: string }) {
  const { mutate: deleteTemplate, isPending } = useDeleteTemplate()
  
  const handleDelete = () => {
    if (confirm('Delete this template?')) {
      deleteTemplate(templateId)
    }
  }
  
  return (
    <button onClick={handleDelete} disabled={isPending}>
      Delete Template
    </button>
  )
}

Using templates to create goals

Templates can be used to quickly create new goals with predefined structures:
import { useTemplates } from '@features/goals/api/use-templates'
import { useCreateGoal } from '@features/goals/api/use-goals'

function CreateFromTemplate() {
  const { data: templates } = useTemplates()
  const { mutate: createGoal } = useCreateGoal()
  
  const handleUseTemplate = (template: GoalTemplate) => {
    createGoal(template.structure)
  }
  
  return (
    <div>
      <h2>Create from template</h2>
      {templates?.map((template) => (
        <button
          key={template.id}
          onClick={() => handleUseTemplate(template)}
        >
          {template.name}
        </button>
      ))}
    </div>
  )
}

Build docs developers (and LLMs) love