Learning Leptos: Build a fine-grained reactive system in 100 lines of code

Поделиться
HTML-код
  • Опубликовано: 8 сен 2024
  • Today's video shows how the fine-grained reactivity that powers Leptos really works. We'll build our own fine-grained reactive system from scratch and to see how to reactively update user interfaces.
    Leptos is a Rust framework for building web applications. You can find out more at
    GitHub: github.com/gbj...
    Discord: / discord

Комментарии • 67

  • @solid_js
    @solid_js Год назад +166

    Big fine-grained reactivity fan over here!!!!! ❤❤❤❤

  • @bolt7
    @bolt7 Год назад +34

    Thanks, this really demystified the concepts for me. Various pointer types aside it's quite intuitively organized. Big fan of Leptos, I've tinkered with a few Rust web frameworks and it has been the most ergonomic by far.

  • @jd4codes
    @jd4codes Год назад +8

    Wow, one of the easiest voices to listen to on RUclips! Thanks for the video, I'm excited to start my Leptos journey!

  • @zwillx3953
    @zwillx3953 Год назад +6

    That's some impressive coding while presenting , and great explanations along the way

  • @fionawashere1086
    @fionawashere1086 6 месяцев назад +1

    fantastic presentation, thank you so much!
    I'm evaluating leptos for multiple future projects, and it looks very promising to me.

  • @cramhead
    @cramhead Год назад +3

    Such a fun demo and really interesting to see how it works under the covers

  • @DavidBudaghyan
    @DavidBudaghyan 3 месяца назад

    I am new to Rust, new to reactive systems and yet this video makes it so easy to understand the concepts and the inner workings. Thank you for the insightful video and clear explanation!

  • @v-for-victory
    @v-for-victory Год назад +2

    Greg, what a captivating introduction and thorough explanation! I was journeying through RUclips in search of info on Leptos and serendipitously landed on your masterpiece. It was the guiding light I needed. Immense gratitude to you!

  • @henrikakesson4457
    @henrikakesson4457 Год назад +6

    Brilliant! Thanks. Really helped me understand the reactive system!!!

  • @Tigregalis
    @Tigregalis Год назад +2

    This is fantastic. Please make more videos! I'd love to see you go into the reactive scopes.

  • @MichaelMaraist
    @MichaelMaraist 5 месяцев назад

    Just coming over from Svelte4 -> Svelte5 ; having to compare/contrast SolidJS style signals in both those frameworks, and seeing your talk just made EVERYTHING make so much more sense. Thank you.

  • @pertuck
    @pertuck Год назад +4

    This is really helpful. I've been wanting to try Leptos, but I was having difficulty grokking the signals and how the view! macro worked exactly.

  • @neociber24
    @neociber24 Год назад +1

    Great explanation, really made me interested in dive SolidJS and Leptos internals

  • @andredasilva6807
    @andredasilva6807 9 месяцев назад

    That was amazing. I didnt fully understand all the rust parts. But i feel like i finally get signals and effects. Phenomenal video. Thanks a lot

  • @zombiefacesupreme
    @zombiefacesupreme Год назад +1

    Thank you for this content!! Super excited with what you're building here.

  • @InDieTasten
    @InDieTasten Год назад +2

    Would've loved to see you detailing how this system works with effects with multiple code paths, that depend on different signals depending on some other signal, as it will also "discover" all the dependencies as they get relevant during the runtime. Really neat.
    In some cases, it could even be advantageous to remove entries from the hashmap again as they become irrelevant to the effect again, though most likely this kind of micro-management of subscriptions is probably overkill for the mostly straight-forward effects.

  • @verified_tinker1818
    @verified_tinker1818 Год назад +8

    Thanks for video. Super informative. Though the audio is a bit quiet. I'd appreciate it if you could make it louder in the future.
    I wonder how equivalent JS frameworks handle this. On one hand, they don't need to worry about things like RefCells and pointers. On the other, if they _do_ want to implement that (for performance), I imagine it'd be a lot harder, if not impossible. But I doubt they care. The performance gain is probably marginal for most UIs.

  • @fionawashere1086
    @fionawashere1086 6 месяцев назад +1

    31:29 This is exactly why Rust is so great. Even if it's a runtime borrow-check, it's still a borrow-check, and not a data race. ^^
    Same thing in 33:56.

  • @doce3609
    @doce3609 Год назад

    This was really cool.
    Thank you for explaining this so beautifully.
    You should link these videos in the documentation somewhere as a reference maybe.

  • @joaodiasconde
    @joaodiasconde Год назад

    Amazing stuff, great rust skills and great simple design for a non-trivial problem/system

  • @vvvvijjjj
    @vvvvijjjj 8 месяцев назад

    Super cool. Needed to watch it a second time to code along. Thanks a ton !!!

  • @dimashadziq6007
    @dimashadziq6007 9 месяцев назад

    Thank i m new to rust and its so hard for me to tackle wasm closure, your framework are really great and this vidio are plus plus. Now i understand better into borrow checker with your explanation

  • @zactron1997
    @zactron1997 Год назад

    Thanks for this! This is a fantastic explanation on how Leptos works.

  • @MuteObserver
    @MuteObserver Год назад

    Thank-you, a lot of new info to connect up, going to be back to review

  • @ruffianeo3418
    @ruffianeo3418 Год назад +1

    The 2023 (re)-invention of global variables, with lots of code mutating it from everywhere and no where :)
    This was the "model" I used in the 1980s for my C programs. Now I know it was "reactive" not "spaghetti" :)

  • @alpaslaneldemir6904
    @alpaslaneldemir6904 Год назад +2

    Thanks Greg.

  • @AccordionMusicAndMore
    @AccordionMusicAndMore 2 месяца назад

    Great vid! Thanks! Keep them coming ;)

  • @zahash1045
    @zahash1045 9 месяцев назад

    I may be wrong but isn’t this exactly how react hooks work?
    React maintains one giant array where all the state is maintained (don’t need to do because js is dynamically typed) and it returns the reference to read the state and a function to update the state

  • @samhanna7382
    @samhanna7382 Год назад +1

    its good that you are making content!

  • @jhvkgvb
    @jhvkgvb Год назад +1

    Thanks for a great explanation! :)

  • @bigmistqke
    @bigmistqke Год назад +2

    Love this video. Reminds me of solid's 'introduction to reactivity' video. Very very cool to see it for rust/leptos.

    • @bigmistqke
      @bigmistqke Год назад

      Actually made me understand the solid-video better, the whole subscription-context was a part i could never fully grasp. Very well explained!

  • @JustAnotherLight
    @JustAnotherLight Год назад

    love this! thank you

  • @kirglow4639
    @kirglow4639 Год назад +2

    This is awesome. My concern is that these signals and effects don't ever seem to be cleaned up, so the innocent single leak in reality turns into a bigger leak as you add more and more of these signal values. Wondering what the approach is to clean those up when the app no longer needs them / references them. I've also built a reactive system but had to use reference counts everywhere for this reason

  • @tobias3581
    @tobias3581 Год назад

    I’m definitely betting my e-commerce startup on Leptos

  • @feepdake9610
    @feepdake9610 Год назад

    Hi, man. Great content. Very interesting, though hard to grasp in one pass.

  • @paulholsters7932
    @paulholsters7932 Год назад +1

    Very nice. When there will be a rich ecosystem around this framework like a big UI library? Like the Primeng library for Angular? Is such a thing already being build?

  • @jrmoulton
    @jrmoulton Год назад

    This is such a great video

  • @gabrielanghinoni4623
    @gabrielanghinoni4623 Год назад +1

    Nice video, great start! try to ajust the audio next one pls, its too low.

  • @feepdake9610
    @feepdake9610 Год назад +1

    Hi, Greg. Can you make a short video on how one can learn the js/wasm interoperability and how the whole machinery works down one level compared to current video. Maybe just a bunch of links, as you probably won't be interested in sharing deeper secrets you've learned and educating instead of spending time developing.

    • @gbjxc
      @gbjxc  Год назад +2

      Yeah! Are you thinking like a “How to build some basic stuff with Rust and wasm-bindgen” or “How does wasm-bindgen actually work?” If it’s “how to build some basic stuff” I went on Ryan Carniato’s stream a while ago and walked through this- if it’s “how does wasm-bindgen really work” then yeah but it’s over my head a little :-D

  • @jorenboulanger4347
    @jorenboulanger4347 Год назад

    ❤ it really helped

  • @nickbanderson
    @nickbanderson Год назад

    Beautiful

  • @shadamethyst1258
    @shadamethyst1258 Год назад +2

    Very interesting!
    I am wondering, however, if signals (and their associated data stored in Runtime) in leptops ever get freed. I could see this becoming problematic for eg. a popup, where signals and effects are created whenever the popup appears, and won't be needed after the popup closes. Do those values in Runtime just sit there until a page reload?

    • @gbjxc
      @gbjxc  Год назад +5

      No this is just a simplified form of it - in reality they are tied to reactive scopes and disposed of appropriately when different parts of the UI and removed. So in that example, the signals would be disposed after the popup is closed.

  • @TeoDumski
    @TeoDumski 7 месяцев назад

    Could you provide code you created throughout this tutorial? It'd be so helpful to study your code without scrolling youtube video back and forth :p Great work, BTW, many thanks!

  • @GlobalYoung7
    @GlobalYoung7 Год назад

    thank you ❤🎉

  • @brandonhunter3036
    @brandonhunter3036 Год назад

    Nice man!

  • @iippari7
    @iippari7 Год назад

    This was incredibly interesting, and your explanations were very clear :) One thing that stood out to me is the requirement that the initial call to an effect calls and registers the appropriate signals. If, for example, I had an effect that counted how many times it had run, and didn't call the getter of some signal A on the first run, but only on subsequent runs, could I fool the runtime into declaring the effect as having no dependencies (thus, never running) when in reality it uses the value signal A?

    • @gbjxc
      @gbjxc  Год назад

      I don't think this toy version actually does it (I'd have to look back) but in real reactive systems like this dependencies are dynamic, so they always only subscribed to the signals accessed on the previous run. You can manually say "track this signal without reading its value" if you want to, which is basically what you're describing I think... "Always run this effect if this signal changes."

  • @flylord4361
    @flylord4361 Год назад +3

    do you have the project in github?

  • @frantisek_heca
    @frantisek_heca 5 месяцев назад

    How current is it in the context of Leptos versions, please? For example, the logic in this video would be mapped to which Leptos version?

  • @paulycdong
    @paulycdong Год назад

    Perhaps I am a bit late to this great tutorial… on 2:22 , how did you spawn up this web server? And what versions of Leptos and Web sys did you use? I am trying to follow along but the imports seem not to be working… thanks!

  • @zenshade2000
    @zenshade2000 11 месяцев назад

    Does anyone know what that color theme is? I really like it a lot.

  • @dominigon
    @dominigon Год назад

    Nice video, I hoped you would show conditions inside create_effect and how you unsubscribe first before resubscribing again as you explained in other video

  • @zahash1045
    @zahash1045 9 месяцев назад

    Why not set the current running effect in the create effect method instead of run effect method.
    because you only need to figure out which effect depend on which signals only once and not every time the signal is run?

    • @SVVV97
      @SVVV97 9 месяцев назад

      Because in a real system you'd really want to newly figure the dependence out every single run: the basic idea is that you want to minimize how often effects are run at basically any cost.
      If you have have an effect that does something like `if some_signal() { do_something_expensive(signal_1()) } else { do_something_expensive(signal_2()) }` you wouldn't want to rerun the effect if `signal_2` changes while `some_signal` was `true`. Moreover this effect couldn't even subscribe to `signal_2` if `some_signal` started out as false.

  • @jimhrelb2135
    @jimhrelb2135 Год назад

    I got really distracted by the usage of Box::leak earlier in the video. I tried looking around and couldn’t find why we’re using it. Ideas?

    • @gbjxc
      @gbjxc  Год назад +3

      Box::leak() gives you a &'static T, which is very useful in particular cases where you want a lifetime with a static reference so that everything that holds it doesn't need to have a lifetime. In this case as it's called once ever, it's not really a leak per se, just a single allocation that doesn't get deallocated until the end of the program.

  • @drsensor
    @drsensor Год назад

    Some people I know use Leptos with gtk-rs

  • @Wadu436
    @Wadu436 Год назад

    Could you make the runtime 'static with something like lazy_static! as well instead of a Box::leak?

    • @gbjxc
      @gbjxc  Год назад +1

      For sure! In the real library I do it with a thread-local, they’re just slightly more awkward to work with than a static reference so I took the simplest path here.

  • @theplanebrain
    @theplanebrain Год назад

    Is this all static?

  • @danvilela
    @danvilela Год назад +1

    Brooo why did you choose the leptospirosis name????

  • @user-qr4jf4tv2x
    @user-qr4jf4tv2x 11 месяцев назад

    already got lost use leptos::{create_element};
    #[derive(Default)]
    struct Runtime{
    }
    fn main(){
    console_error_panic_hook::set_once();
    let body :HtmlElement=body().unwrap();
    let p =create_element("p");
    p.set_text_content(Some("OK"));
    }

    • @user-qr4jf4tv2x
      @user-qr4jf4tv2x 11 месяцев назад

      |
      301 | pub struct HtmlElement {
      | ^^^^^^^^^^^ --
      help: add missing generic argument
      |
      11 | let body :HtmlElement=body().unwrap();
      | ++++
      error[E0425]: cannot find function `create_element` in this scope
      --> cache_front\src\main.rs:13:12
      |
      13 | let p =create_element("p");
      |