Dynamically generating components creates a new concept called ownership. More here...
Keys
In the above example what would happen if the contents of text were dynamically changing? For example if it was associated with a text box that the user was typing into, and we updated text whenever a word was entered.
In this case as the user typed new words, the word_count would be updated and the list would change. However actually only the contents of one of the list items (LI blocks) would actually change, and perhaps the sort order. We don't need to redraw the whole list, just the one list item that changed, and then perhaps shuffle two of the items. This is going to be much faster than redrawing the whole list.
Like React, Hyperstack provides a special key param that can identify child elements so that the rendering engine will know that while the content and order may change on some children, it can easily identify the ones that are the same:
You don't have to stress out too much about keys, its easy to add them later. Just keep the concept in mind when you are generating long lists, tables, and divs with many children.
Application defined components can also receive and render children. A component's children method returns an enumerable that is used to access the unrendered children of a component. The children can then be rendered using the render method which will merge any additional parameters and render the child.
Rendering Multiple Values and the FRAGMENT component
A render block may generate multiple values. React assumes when a Component generates multiple items, the item order and quantity may change over time and so will give a warning unless each element has a key:
If you are sure that the order and number of elements will not change over time you may wrap the items in the FRAGMENT pseudo component:
class Indenter < HyperComponent
render(DIV) do
IndentLine(by: 10) do # see IndentLine below
DIV {"Line 1"}
DIV {"Line 2"}
DIV {"Line 3"}
end
end
end
class IndentLine < HyperComponent
param by: 20, type: Integer
render(DIV) do
children.each_with_index do |child, i|
child.render(style: {"margin-left" => by*i})
end
end
end
class ListItems < HyperComponent
render do
# without the keys you would get a warning
LI(key: 1) { 'item 1' }
LI(key: 2) { 'item 2' }
LI(key: 3) { 'item 3' }
end
end
# somewhere else:
UL do
ListItems()
end
class ListItems < HyperComponent
render(FRAGMENT) do
LI { 'item 1' }
LI { 'item 2' }
LI { 'item 3' }
end
end