View() called before WindowSizeMsg
Robert-M-Muench opened this issue · comments
Note that
WindowSizeMsg
is sent before the first render and then again every resize.
Originally posted by @meowgorithm in #43 (comment)
My current program's View()
function gets called before I get a WindowSizeMsg
which makes it impossible to know how to size my output. How can this be possible?
This is the call stack when View()
is called:
And this is the call stack when Update()
is called:
You can see that the Update()
(line: 547) comes later in the tea.go.StartRetruningModel code as the View()
(line: 405) call.
Hi! The query for the initial window size runs asynchronously so that it doesn't hold up the program startup (since many programs don't need the window size). As a result, it's very possible that the initial view can be called before the window size is queried. If your program does depend on knowing the window size the general pattern is to set a flag on your model when the window size comes in and manage output in your view accordingly.
Here’s a contrived example of how it's commonly done with a notion of application state:
package main
import (
"fmt"
"os"
tea "github.com/charmbracelet/bubbletea"
)
type state int
const (
initializing state = iota
ready
)
type model struct {
state state
width, height int
}
func (m model) Init() tea.Cmd {
return nil
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
return m, tea.Quit
case tea.WindowSizeMsg:
m.width, m.height = msg.Width, msg.Height
m.state = ready
}
return m, nil
}
func (m model) View() string {
if m.state == initializing {
return "Initializing..."
}
return fmt.Sprintf("This is a %dx%d size terminal.", m.width, m.height)
}
func main() {
if err := tea.NewProgram(model{}).Start(); err != nil {
fmt.Println("uh oh:", err)
os.Exit(1)
}
}
Of course, for simple programs you could eliminate the state portion and just check and see if width
or height
is greater than 0
.
Ok, thanks. The async explains it. Not sure if this is mentioned in the docs somewhere. If not, I think it's worth doing.