FlickDocumentation

Context hooks

Call Swift actions, observe app state, and request changes from a Flick.

Use context hooks to call your app’s Swift actions and read or update its published state. Flicks opened through the Flick control receive the APIs allowed for their selected scope and declared capabilities.

Named views mounted with Flick(.card, title: "Hello") receive their explicit inputs as props. Context hooks access the host registry through a control-launched execution.

HookUse it toReturns
useContextActionCall a Swift actionA function with the action’s input and output types
useContextObservationRead a value published by SwiftThe latest value
useContextStateRead and update a value with a Swift setter[value, setValue]

These examples use MyApp from the Swift quick start. Its generated package, com.acme.myapp, gives TypeScript the types declared in Swift. Pass its descriptors, such as MyApp.states.count, to the matching hook.

useContextAction

Get a function that calls a Swift action. This button invokes the quick start’s increment handler:

Flick.tsx
import { Button, useContextAction } from '@flickfyi/core'
import { Effect } from 'effect'

// Generated from MyApp's Swift declarations by the SDK's parser
// flkr links this bundle-ID package to ../generated
import { MyApp } from 'com.acme.myapp'

export default () => {
  // Swift: @FlickAction(failure: Never.self) case increment
  // Returns () => Effect.Effect<void, never>
  const increment = useContextAction(MyApp.actions.increment)

  return (
    <Button onClick={() => {
      // increment() creates the Effect; runPromise executes the Swift handler
      return Effect.runPromise(increment())
    }}>
      Increment
    </Button>
  )
}

The action’s generated type determines its arguments and result. This action takes no input and returns an Effect that completes with void.

Effect.runPromise returns a Promise for that completion.

For typed inputs, results, failures, and streamed actions, see Expose actions. The hook preserves those types; execution depends on whether the action returns an Effect or Stream.

useContextObservation

Read a value the app publishes without a setter. The quick start’s case count(Int) becomes a TypeScript number:

Flick.tsx
import { Text, useContextObservation } from '@flickfyi/core'
import { MyApp } from 'com.acme.myapp'

export default () => {
  // Swift publishes count through observeForFlick
  const count = useContextObservation(MyApp.states.count)

  return <Text>Count: {count}</Text>
}

The hook returns the latest published value and rerenders the component when it changes. It subscribes while your component is mounted and unsubscribes when it unmounts.

useContextState

Read a value and request updates through the app’s Swift setter. Add set: to the quick start’s count registration:

MyApp/ContentView.swift
// In your SwiftUI view, with @State var count = 0
// Other view modifiers…
.observeForFlick(count, for: \.count, set: { count = $0 }) {
    Flick.Publish($0)
}
Flick.tsx
import { Button, Flex, Text, useContextState } from '@flickfyi/core'
import { MyApp } from 'com.acme.myapp'

export default () => {
  // Swift supplies both the published count and its setter
  // For read access alone: const [count] = useContextState(MyApp.states.count)
  const [count, setCount] = useContextState(MyApp.states.count)

  return (
    <Flex>
      <Text>Count: {count}</Text>
      <Button onClick={() => setCount(current => current + 1)}>
        Increment
      </Button>
      <Button onClick={() => setCount(0)}>Reset</Button>
    </Flex>
  )
}

The setter accepts a value (setCount(0)) or an updater (setCount(current => current + 1)) and returns void.

Swift handles each request and republishes its value. React displays that published value, including any validation or transformation the app applies.

See Publish state for more Swift setter examples, including selecting an item and transforming the published value.

The generator distinguishes read-only and writable state by the Swift registration. TypeScript rejects useContextState for a read-only value and useContextObservation for a writable one.

Handle unavailable context

Actions and state are available while their Swift registrations are mounted and exposed to the Flick. Required access is the default: an unavailable API throws Flick context is not mounted.

Pass { optional: true } when your component can render without that API. The hook returns undefined while it is unavailable and updates when availability changes:

Flick.tsx
import { Button, Flex, Text, useContextState } from '@flickfyi/core'
import { MyApp } from 'com.acme.myapp'

export default () => {
  const counter = useContextState(MyApp.states.count, { optional: true })

  // Call hooks before conditional returns
  if (counter === undefined) {
    return <Text>Open the counter in your app</Text>
  }

  // The whole tuple is undefined until the state is available
  const [count, setCount] = counter

  return (
    <Flex>
      <Text>Count: {count}</Text>
      <Button onClick={() => setCount(current => current + 1)}>
        Increment
      </Button>
    </Flex>
  )
}

All three context hooks accept this option:

HookResult while unavailable
useContextAction(action, { optional: true })undefined instead of the callable function
useContextObservation(value, { optional: true })undefined instead of the published value
useContextState(value, { optional: true })undefined instead of the [value, setter] tuple

Runtime failures still throw with optional: true. Calling an action or setter after its Swift registration unmounts also throws. Action failures follow the action’s generated Effect or Stream type.

A published Swift optional maps to null when empty. undefined means the API itself is unavailable.

Component state and view inputs

Use React’s useState for values owned by your component, such as an expanded row or an input draft. Context hooks read and write values owned by the host app. Named-view inputs arrive as component props.

Call hooks at the top level of a component or custom hook, following the React rules of hooks. Invoke actions and setters from event handlers.