In CS, a component (vs a hook) can be placed any where instead of being restricted at the top of render code and not in if, loop code like Hooks.
For example, here is a state declared in a IF condition:
cs(
["count1", ({}, next) => State({initValue: 0, next})],
({count1})=>(
<div>
Count 1: {count1.value}
<button onClick={() => count1.change(v=>v+1)}>plus</button>
{count1.value < 2 && cs(
["count2", ({}, next) => State({initValue: 0, next})],
({count2})=>(
<div>
Count 2: {count2.value}
</div>
),
)}
</div>
),
);
In above example, there are 2 count states, but only count1 is declared at the top level stack. The second state "count2" will be created only if count1 value is > 10 and it will be used only inside that condition. Also when the that condition is no longer true, the state count2 would be destroyed.
Here is another example that a state is declared in a loop:
<div>
A shopping list:
{["Apple", "Orange", "Tomato"].map((item)=> cs(
keyed(item),
["count", (_, next) => State({initValue: 0, next})],
({count}) => (
<div key={item}>
{item}: {count.value}
<button onClick={() => count.change(v=>v+1)}>+</button>
<button onClick={() => count.change(v=>v-1)}>-</button>
</div>
),
))}
</div>
In the above example, with each item in the shopping list, a different "count" state will be declared, and they can be interacted with (+ or -) independantly
In CS architecture, when a component need a state, it renders a state node into Virtual DOM tree, same goes for Static reference (or Memo in Hooks) or other effects like OnMounted, OnUnmounted... each function is rendered as a separated node into the Virtual DOM tree. Which means a component will be consisted of multiple "basic" nodes, each one is responsible for a function.
On the other hand, in Hooks, a component is always rendered as a Virtual DOM node, and each time that component needs a state, it will use a space in the state of that Virtual DOM node. This means no matter how many time you call "useState", there is only 1 node's state being accessed and used. Same goes for all other effects like useEffect, useMemo...
In CS, a custom Component is much more powerful than a Custom Hook
A custom component declared in CS way is capable of doing everything that a Custom Hook can do, and much more. A CS custom component can block the rendering, or loop rendering, and other actions to control the logic flow of the rendering (like combining 2 rendering flow).
Here is an example of a custom component which blocks the rendering altogether
const App = () => cs(
["blocker", (_, next) => Blocker({next})],
({blocker}) => (
<div className="">
Click this <button onClick={() => blocker.blockNow()}>button</button> and
everything will disappear
</div>
),
);
const Blocker = ({next}) => cs(
["blocked", (_, next) => State({initValue: false, next})],
({blocked}) => !blocked.value && (
next({blockNow: () => blocked.onChange(true)})
),
);
In the above example, there is a custom component call Blocker. Blocker itself declares a state called "blocked" and with initial value of "false". If that "blocked" state somehow is "true", then the "next" function will not be called and "everything will disappear".
The Blocker component exports a method called "blockNow" which upon invoked will simply change the "blocked" state to "true" and "everything will disappear".
Here is another example that loops rendering:
const App = () => cs(
["shoppingItem", (_, next) => LoopMe({list: ["Apple", "Orange", "Tomato"], next})],
({shoppingItem}) => (
<div>
Item: {shoppingItem}
</div>
),
);
const LoopMe = ({list, next}) => (
list.map((item, i) => (
<div key={i}>
{next(item)}
</div>
))
);
In the above example, the LoopMe component receive a list of items, and all the rendering logic below it is repeated with each item in the list, which mean this code is actually rendered 3 times.
<div>
Item: {shoppingItem}
</div>
Here is another example that combine 2 rendering flows:
const App = () => cs(
({}, next) => SecondFlow({next}),
({}) => (
<div>
This is flow 1
</div>
),
);
const SecondFlow = ({next: rootNext}) => cs(
({}, next) => CombineFlow({flow1: rootNext, flow2: next}),
() => (
<div>
This is flow 2
</div>
)
);
const CombineFlow = ({flow1, flow2}) => <>
{flow1()}
{flow2()}
</>;
In the above example an additional content is added to the main rendering code. This technique is important to implement components like Tooltip or Modal, where "SecondFlow" component declares how that Tooltip (or Modal) looks like, and the CombineFlow make sure that the additional content only appears when user hover their mouse over a text (Tooltip) or click a button to open the Modal.