Skip to content
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

Compiling use_context hook example fails #1753

Closed
2 of 8 tasks
xosxos opened this issue Feb 21, 2021 · 4 comments · Fixed by #1770
Closed
2 of 8 tasks

Compiling use_context hook example fails #1753

xosxos opened this issue Feb 21, 2021 · 4 comments · Fixed by #1770

Comments

@xosxos
Copy link
Contributor

xosxos commented Feb 21, 2021

This is about:

  • A typo
  • Inaccurate/misleading documentation (e.g. technically incorrect advice)
  • Undocumented code
  • Outdated documentation
  • Other

Problem

The use_context hook example does not work.
https://yew.rs/docs/en/next/concepts/function-components/pre-defined-hooks

Steps To Reproduce

  1. Create a Yew project
  2. In Cargo.toml add dependencies
yew = {git = "https://github.com/yewstack/yew"}
yew-functional = {git = "https://github.com/yewstack/yew"}
yew-functional-macro = {git = "https://github.com/yewstack/yew"}
  1. Copy paste example code into app.rs
  2. Add the following imports to app.rs
use yew::html;
use yew_functional::{function_component, use_state, ContextProvider, use_context};
use std::rc::Rc;
  1. The compiler gives the following error
error[E0277]: the trait bound `yew::virtual_dom::VComp: Transformer<Rc<Theme>, Theme>` is not satisfied
  --> src/app.rs:19:41
   |
19 |         <ContextProvider<Theme> context=ctx>
   |                                         ^^^ the trait `Transformer<Rc<Theme>, Theme>` is not implemented for `yew::virtual_dom::VComp`
   |
   = help: the following implementations were found:
             <yew::virtual_dom::VComp as Transformer<&'a T, Option<T>>>
             <yew::virtual_dom::VComp as Transformer<&'a T, T>>
             <yew::virtual_dom::VComp as Transformer<&'a str, Option<String>>>
             <yew::virtual_dom::VComp as Transformer<&'a str, String>>
           and 3 others
   = note: required by `transform`

Questionaire (Optional)

  • I'd like to write this documentation
  • I'd like to write this documentation but I'm not sure what's needed
  • I don't have time to add this right now, but maybe later
@siku2
Copy link
Member

siku2 commented Feb 21, 2021

@hamza1311, care to take a look? :)

@ranile
Copy link
Member

ranile commented Feb 21, 2021

This happens because use_state returns a Rc<Theme> and ContextProvider<Theme>'s context prop accepts a Theme and fails when it receives a Rc<Theme>. We can fix the example in 3 ways:

  1. Deref and clone ctx value before passing: context=(*ctx).clone()
  2. Double-Rc the value
<ContextProvider<Rc<Theme>> context=ctx>
    <Consumer />
</ContextProvider<Rc<Theme>>>

// in consumer:
let theme: Rc<Rc<Theme>> = use_context().expect("no ctx found");
  1. Use a type which implements Copy so it can just deref without needing to be cloned but that's kinda cheating.

The bigger problem is the hooks API as neither of those solutions are elegant. A better API was proposed in #1026 (comment) which could alleviate the problem to an extent but I'm not sure what the best solution the API problem is.

@xosxos
Copy link
Contributor Author

xosxos commented Feb 21, 2021

I went with (*ctx).clone() and its working and I am happy !

Also worth mentioning that the following line in the example needs to be without the Rc<> to get it to work.

    let theme = use_context::<Rc<Theme>>().expect("no ctx found");

Although a lot of work remains to be done with the hooks, overall I am very very very impressed by the progress..!

@lukechu10
Copy link
Contributor

The bigger problem is the hooks API as neither of those solutions are elegant. A better API was proposed in #1026 (comment) which could alleviate the problem to an extent but I'm not sure what the best solution the API problem is.

The underlying problem is still #1656. Then there wouldn't be any need for Rcs. ContextProvider might even take a reference without cloning but I am not sure if that is possible. I'm guessing child components are destroyed first but I might be wrong. If they are indeed dropped first, we can be sure that the reference would be valid in the child components as long as the ContextProvider has not yet been destroyed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants