Tutorials

Real-Time Updates

Handle real-time data with channels and subscriptions.

Build real-time apps with external data streams!

The Pattern

package main

import (
    "fmt"
    "time"
    tea "github.com/charmbracelet/bubbletea/v2"
)

type model struct {
    messages []string
    sub      chan string
}

type newMsgMsg string

// listenForMessages returns a command that listens to the channel
func listenForMessages(sub chan string) tea.Cmd {
    return func() tea.Msg {
        return newMsgMsg(<-sub)  // Block until message received
    }
}

func (m model) Init() tea.Cmd {
    return listenForMessages(m.sub)
}

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
    switch msg := msg.(type) {
    case tea.KeyPressMsg:
        if msg.String() == "q" {
            return m, tea.Quit
        }
    case newMsgMsg:
        m.messages = append(m.messages, string(msg))
        return m, listenForMessages(m.sub)  // Listen again!
    }
    return m, nil
}

func (m model) View() string {
    s := "Real-time messages:\n\n"
    for _, msg := range m.messages {
        s += "" + msg + "\n"
    }
    return s + "\nPress q to quit"
}

func main() {
    sub := make(chan string)
    
    // Simulate external data
    go func() {
        for i := 1; ; i++ {
            time.Sleep(time.Second)
            sub <- fmt.Sprintf("Message %d", i)
        }
    }()
    
    tea.NewProgram(model{sub: sub}).Run()
}

The Key Insight

Commands that block on channels let you react to external events!