-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Function Components & Hooks V2 #2401
Conversation
Visit the preview URL for this PR (updated for commit 806f618): https://yew-rs--pr2401-fc-hook-v2-ziafg6gv.web.app (expires Thu, 03 Feb 2022 14:27:51 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First off, I like the push towards linting for hooks.
Many of my review comments stem from the simple fact that I don't think function components are the end-all-be-all of design. With BaseComponent
being sealed, there seems to be some serious push towards building a walled-garden and I don't see how that's a good thing:
- Anyone writing hooks is subjected to the syntax-based rewriting of the
#[hook]
attribute. Instead of exposing the functionality by a clean interface, such as atrait
, it's exposed under the opaqueness of a proc-macro and can't be accessed otherwise. Protecting the user from himself beside - the usual mechanics of saying "I know what I'm doing, let me peek under the hood" of rust - unsafe functions - can't be used. - Most of this is based on making
use_hook
private. Are you saying that it's impossible somebody outside yew to correctly use it? If yes, then I'd like to hear more reasons why. If no, I wonder why that method can't be markedunsafe
or similar guarded with warnings about what exactly is "unsafe" about using it directly. - By making
use_hook
private, anybody writing custom hooks has to, at some point, call one of the Pre-defined Hooks, there's no way around that. I can't agree with that until I see some good reason that the pre-defined hooks are sufficient for any but the most fringe applications.
Besides those concerns, I had a quick look at the code, but skipped the syntax transformations in the hook proc macro for now.
packages/yew-macro/src/hook/body.rs
Outdated
if m.to_string().starts_with("use_") { | ||
if self.is_branched() { | ||
emit_error!(m, "hooks cannot be called at this position."); | ||
} else { | ||
*i = parse_quote_spanned! { i.span() => ::yew::functional::Hook::run(#i, #ctx_ident) }; | ||
} | ||
|
||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I take it that this design means I can't call any function starting with use_
that is not a hook and false positives are a conscious trade-off? How do I turn this off when such a false positive occurs?
I have some doubts that this kind of syntax guided rewriting is maintainable in the long term, do you know any bigger library that uses this approach successfully to convince me that it's not going to break on us in the future?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do I turn this off when such a false positive occurs?
use some_crate::{use_something as not_a_hook} ;
that uses this approach successfully
This is used in std as well, which I will reply to the main comment instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@futursolo we should mention this in the error to be more user friendly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no way to do it. The procedural does not know the type of your expression.
The only error will be from the compiler saying that use_something
does not implement Hook
.
Do you think
The If you are confident with using
This is always the case in Rust?
How do you poll a future manually inside a future? Short answer, It's not possible (as
What would an
There's no way around that in React either. If you don't need |
Yes, in some code, but probably not here. Maybe with an additional feature but I don't think it's feasible for yew. What's that got to do with making it impossible for library code to emulate EDIT: An explicit example, I had generator components working. I could see a very simple change to change them to be able to suspend, just changing
And yet, the actual implementation that shipped in stable is much more deeply engrained in the language grammar and a larger part of the compiler. That doesn't really convince me that rebuilding such a transformation is a smart idea.
You can use
That'd be a fine sentiment if this were simple a React clone. Alas, blindly trodding the path of Facebook is not really the approach I'd like to see.
Haven't seen that, can you link the relevant issue and discussion? The only open issue/discussion mentioning it is this PR. Losing it would mean losing access to |
I don't think Yew is an elite hacker toy for one to play with.
Neither of these applies to hooks.
You cannot do any async IO without the access to the original context unless you await on it.
If a component is suspendible, then consider the following code: use_a_low_level_hook();
use_a_suspendible_hook()?; For any hook before a suspension, I don't (and I believe most maintainers don't either) have time to explain to everyone about why their new low-level hook with This is going to be the case for all components if Yew eventually switches to a concurrent renderer. ( In addition, the post_render call is not called on SSR but callback is and callback calls does not reliably re-render even if it returns true unless currently suspended. TL; DRIn short, I don't think these objections were done based on legit ground / issues that already demonstrated the limitation of the design but speculations around potential possibility of the limitation of either some issue may surface or a new design may supersede function component. Potential bugs happen with any design and it needs time for it to become polished. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many of my review comments stem from the simple fact that I don't think function components are the end-all-be-all of design. With
BaseComponent
being sealed, there seems to be some serious push towards building a walled-garden and I don't see how that's a good thing:
Is there a case where you need BaseComponent
and can't use Component
? According to my understanding, it's merely a wrapper around Component
to do some type system magic with the return type of view
method to allow writing cleaner code. If that is not the case, I'm in favor of exposing of BaseComponent
.
We should allow library authors to add different types of components (like generator components). That path shouldn't be closed.
What would an
unsafe fn
accomplish if a hook is unsafe? It does nothing than requiring a unsafe block being around it.
You can have unsafe code inside of a function even if it's not unsafe.
unsafe
denotes, "I know what I'm doing and I uphold the guarantees required to make this code sound/safe/correct". I think that is relevant here.
use_hook
is no longer exported. (The methods it provides are not safe in SSR and Hydration for a reason similar to struct components. Users should use a combination of built-in hooks instead.)
This is exactly what unsafe should specify.
use_hook is actually subject to removal.
Haven't seen that, can you link the relevant issue and discussion? The only open issue/discussion mentioning it is this PR. Losing it would mean losing access to
HookUpdater
, again, for no reason I can see, the API seems fine.
Why not just remove it now? HookUpdater
can be exposed with an unsafe
API where the safety guarantees are clearly documented.
I must admit, I mostly glanced over the code. I'll review in more in depth soon.
packages/yew-macro/tests/function_component_attr/hook_location-fail.stderr
Outdated
Show resolved
Hide resolved
packages/yew-macro/tests/function_component_attr/hook_location-pass.rs
Outdated
Show resolved
Hide resolved
I don't disagree with this but In addition, I highly doubt a stateful API at render time (generator component) would do any good. If we were to give Yew Concurrent Mode, then
unsafe is used on when memory safety is not guaranteed and not anything "use at your own risk". https://doc.rust-lang.org/std/keyword.unsafe.html
https://doc.rust-lang.org/std/future/trait.Future.html
There's actually a limitation on the trait as the trait method is safe.
Because I am lazy? Keeping In addition, the low-level API needs to be provided for a good reason. I don't think there's any circumstances that you need the low level API and it's not achievable with the built-in hooks. (callback with |
I agree here. Let's not expose the APIs, at least not now.
We should properly document API that may end up in causing surprising behavior/headache for consumer. I was wrong about unsafe so let's not use it.
That's fair. It's fine as it is too
Agreed. We should not be against exposing the APIs though so if someone comes up a valid use case, we should provide the API required for it. In any case, I'll try to review this either today or tomorrow. Hopefully we can get merged soon. |
This Pull Request now no longer includes a This eliminates heap allocations from subsequent renders in hooks if that hook is not updated / changed and reduces code size comparing to master. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Thanks for your PRs and helping push Yew forward.
Description
Fixes #2364
Fixes #2343
Fixes #2026
Summary of Changes:
#[hook]
.#[function_component]
&#[hook]
.use_
prefix.use_hook
has ceased to exist.use_ref
is renamed touse_memo
and re-calculates its value when the dependency change.Still Missing:
Checklist
cargo make pr-flow
(cargo make pr-flow is broken on macOS? pr-flow is broken on macOS #2403)