-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
README suggestions #16
Comments
Thanks for the tips!
|
Re:
Which literally was the primary reason I added For a readme intro though I can use a simple ternary. I think I was just excited to use |
Update the state docs to include more computed-signal examples and be a bit more introductory (slowly introducing topics one by one): https://github.com/heyheyhello/haptic/blob/main/src/state/readme.md |
The caching feature in It's actually not what I expected, and I can see this potentially creating a few problems. Let's say I have a set of tab panels and use
That last one worries me in particular. The way I like to explain UI state in general, is I like to distinguish between application state and control state - the difference being, application state is relevant for as long as the application runs, while control state is only relevant while a control exists. The native DOM example is a dropdown selector: you don't expect to switch to a different tab in your application or something, and come back to find the dropdown is still somehow dropped-down. The userland example (for which you'd build a custom component) is something like a date-picker, where, again, if you switch away from a tab, you don't expect to come back and find the date-picker is still opened to some random month you had navigated to before deciding to switch to a different tab. The "is open" and "current month" states are only relevant while the control is visible, and it is instance-dependent, so you would use local state for that. Caching in this manner kind of mucks up that distinction. What used to be control state will now hang around indefinitely. In a different context, your components would have a life-cycle where the control state resets when they disappear from the view, but suddenly this works differently. If you have reusable components with control state, and you introduce That's not to say the feature is useless by any means! I'm sure it's very useful for some cases. Just that it seems risky to encourage use of this as a default. It's probably something that should be brandished as an optimization? With the memory and component state caveats. As with anything, you don't reach for performance optimizations unless you have a performance problem - "premature optimization" and all that...
Me neither. I couldn't make heads or tails of it, which was part of the reason I decided to just conceptualize of the problem myself and implement a solution. I don't know how you get by without it. Never use lists?? 😄 ... so I will probably try to port mine at some point, and we'll see how that pans out. 🙂 |
Interesting points, thanks. I think I was eager to figure out how to switch content with minimal work. I wrote <div>
{wire($ =>
data.count($) > 5
? (log('render T'), <p>There are more than 5 clicks</p>)
: (log('render F'), <p>Clicks: {wire(data.count)}</p>)
)}
</div> It works, but it's bad.
In I went to see how Solid's compiler handles ternaries. It's really good stuff! Take a look at this... It memos the condition expression into a new signal, such that I can do this in Haptic too by making a signal based on an expression: /** Create a signal based on an expression */
const signalFrom = <T>(cond: ($: SubToken) => T): Signal<T> => {
let s: Signal<T> | undefined;
wire(($) => {
const c = cond($);
if (!s) s = signal.anon<T>(c); // First run
else if (s() !== c) s(c);
})();
return s!;
};
<div>
{wire($ =>
signalFrom($ => data.count($) > 5)($)
? (log('render T'), <p>There are over 5 clicks</p>)
: (log('render F'), <p>Clicks: {wire(data.count)}</p>)
)}
</div>; Note I can't use a computed-signal here because they're lazy and only calculate the conditional when they're read, so they're for a different use case; It'll run the T branch and F branch once each 😄 The wire created by I'll put this in the stdlib and use it on the front page of the readme after I think about it a bit more... Let me know any thoughts.
Yeah lol. Honestly I never use more than like 10 elements so I just recreate them every run 🙃. I have a solution for #17 though. |
So your todo-list app will have a limit of 10 todos? I guess that motivates people to complete their todos 😂 Jokes aside, I love I like the idea that I can largely organize state and derived state at the top of my program - as opposed to computing derived states on the fly, inline with JSX. Of course, regularly functions can do that - but the cascading updates that flow from signals to computed signals, it just seems like a natural extension of the reactive mindset. Even if it's a little wasteful and unnecessary at times, I still like it, because consistency - it seems to reduce the amount of refactoring needed, like when something that was just a function needs to become reactive for some reason... it already is. For me, it's like, if this is how I've decided to manage my state, that's how I'm going to manage all my state. (the inconsistencies is one of the things that bug me more than anything about React - you have this use-case? use this pattern. oh now this other thing gets introduced? now you want that pattern instead... state management is terribly inconsistent in React, and I think that's one of the reasons there's a new state management library every two weeks...) |
A couple of suggestions for the example in the README.
Add
/** @jsx h */
to the top - just to be explicit, and so newbs don't have to spend time figuring out how to change the default in a.babelrc
or something.The
when
example was a bit confusing, since it's actually unnecessary - awire
with a ternary expression would work just as well. Newcomers might perceive this example as "ternaries are not available", which would be a bad, since those are idiomatic to most JSX libraries. I would go with a simple ternary here, which demonstrates reactive expressions - and maybe a separate example with 3 options, maybe color-choices in a drop-down?I'd like to see an example of a computed expression here as well - maybe just put the
state.text($).length
behind a computed? I actually forget what those even looked like. It's such an important feature, so it would be good to cover this in the example, so people are exposed to it right away.I immediately wanted to add
autofocus
to that input - which doesn't work, and I guess it can't "just work", since the elements aren't in the DOM at the time when it's being applied? From there, I start wondering about life-cycle events and can I manually focus the input after it's mounted... So this one might be worthy of a separate issue and further discussion.I only had a short time playing around, as I wasted too much time trying to get CodeSandbox to work properly with
.tsx
- but this looks really promising and I'm super excited to try this out!Where are we on
map
? I had a basic, working implementation in my own toy Sinuous clone here which might help you get the ball rolling - presumably it would need something like the snabbdom diff algorithm?I know you have quite a bit of work to do on tests and such, but
map
is likely all that's all that's missing for me to start porting some of my example projects from Sinuous to Haptic, which I would love to do. (If I can find the time, I might try to prototype an implementation ofmap
myself.)Great work, man! So stoked to see where this goes. 😄
The text was updated successfully, but these errors were encountered: