Skip to content

Commit

Permalink
Render callback tutorial (#356)
Browse files Browse the repository at this point in the history
  • Loading branch information
dphfox authored Jun 27, 2024
1 parent 34f278c commit d93101f
Showing 1 changed file with 90 additions and 1 deletion.
91 changes: 90 additions & 1 deletion docs/tutorials/best-practices/callbacks.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,93 @@ local function Button(
end
```

This is the primary way components talk to their controlling code in Fusion.
This is the primary way components talk to their controlling code in Fusion.

-----

## Render Callbacks

There's a special kind of callback that's often used when you need more control
over the children you're putting inside of a component.

When your component asks for `[Children]`, the controlling code will construct
some children for you ahead of time, and pass it into that `[Children]` key. You
don't have any control over what that process looks like.

```Lua
-- This snippet...
local preRendered = scope:Dialog {
[Children] = {
scope:Button {
Text = "Hello, world!"
},
scope:Text {
Text = "I am pre-fabricated!"
}
}
}

-- ...is equivalent to this code.
local children = {
scope:Button {
Text = "Hello, world!"
},
scope:Text {
Text = "I am pre-fabricated!"
}
}

local preRendered = scope:Dialog {
[Children] = children
}
```

However, if your component asks for a callback instead, you can create those
children on demand, as many times as you'd like, with whatever parameters you
want to pass in.

This callback should be given a descriptive name like `Build`, `Render`, or
whatever terminology fits your code base. Try and be consistent across all of
your components.

```Lua
local preRendered = scope:Dialog {
-- Use a `scope` parameter here so that the component can change when these
-- children are destroyed if it needs to. This is especially important for
-- components that create multiple sets of children over time.
Build = function(scope)
return {
scope:Button {
Text = "Hello, world!"
},
scope:Text {
Text = "I am created on the fly!"
}
}
end
}
```

Render callbacks are especially useful if the calling code needs more
information to build the rest of the UI. For example, you might want to share
some layout information so children can fit into the component more neatly.

```Lua hl_lines="2 6 10"
local preRendered = scope:Dialog {
Build = function(scope, textSize)
return {
scope:Button {
Text = "Hello, world!",
TextSize = textSize
},
scope:Text {
Text = "I am created on the fly!",
TextSize = textSize
}
}
end
}
```

This is also useful for [sharing values to all children](../sharing-values),
which will be covered on a later page.

0 comments on commit d93101f

Please sign in to comment.