Lessons learnt as a new leptos user coming from React #1451
Replies: 2 comments 7 replies
-
Fully agreed, that is also what I was hoping for.
In my opinion the problem isn't really solved because the more re-usable As a result, I don't really see a good general solution yet regarding building components to be reactive from the ground up. I rather had the impression there is a tendency to write components that only support what they have to for the particular use case. In fact, that's currently my main gripe about leptops compared to Solid/React: If writing generally re-usable components isn't out-of-the box and takes considerably more effort, the ecosystem is much harder to grow in general. |
Beta Was this translation helpful? Give feedback.
-
Thank you for sharing experience! |
Beta Was this translation helpful? Give feedback.
-
I'm just gonna document the pitfalls and lessons learnt as a (fairly) new leptos user. Hopefully some of these can be included in the documentation in case they can help someone else.
Context: This is all coming from a person who's not into frontend (I'm mostly a backend dev), but I have worked a fair amount on React. I know a lot about frontend (vanilla and react), but hate it. I love rust, so hopefully leptos is the answer for me. Anybody who's switching to leptos from React might find this useful.
Lession 1: Everything is reactive
This is probably obvious to anyone who's a leptos or SolidJS user, but one of my biggest lessons would be that there is no VDom. Which means, this:
Will be enabled / disabled at the start when the component is rendered, and when
is_enabled
changes, it will not update. The way to tell leptos that the prop is dynamic is to provide it a closure mentioning that the prop needs to be updated when the signal changes.Relevant documentation: https://leptos-rs.github.io/leptos/view/02_dynamic_attributes.html
The good news is that I noticed a warning in the console when I used a signal without a closure, so that's nice!
Lesson 2: Build your components to be reactive
This is kinda an extension of the previous one, but since everything needs to be reactive, all your props need to be able to accept either a static value, or a closure that can dynamically provide the value. Thankfully, you don't need to use complex type magic and generics for this. Leptos provides a
MaybeSignal
type that can be used as a prop. Simple example.Instead of writing this:
Write this:
Big lesson here:
Build your components to be reactive from the ground up!! Sure, the console gives you a warning when you use a signal in a non-reactive way, but if you build your codebase to be reactive only when you need it to be, and it becomes too complex over time (as it naturally will), finding out where you need to update your code to be reactive would be a BIG pain. The best way would be to have your components to be reactive from the ground up, so that you can use them reactively when you need to, and forget about reactivity when you don't. The
MaybeSignal
type is a big plus here. Just swapping all your props forMaybeSignal
pretty much solves the problem.Relevant documentation: https://docs.rs/leptos/latest/leptos/enum.MaybeSignal.html
Lesson 3: Props can be optional!
Yeah, this would seem pretty obvious for a react user, but as somebody who works a lot in rust, having stuff that are optional seems weird, since I'm used to declaring things explicitly. I don't know what macro magic is running behind the scenes (I hope to one day when I get more time), but props can indeed be optional. If they are marked as optional, they would require a
Default
implementation. If not, you can provide one.Relevant documentation: https://leptos-rs.github.io/leptos/view/03_components.html#optional-props
Lesson 4: Use heap allocation more with
into
It would be tempting to use
&str
everywhere instead ofString
to avoid an unnecessary allocation, but the more I work with this, the more I realize that it starts to become premature optimization. When writing backend code, using&str
seems pretty common, tbh. That's mostly because it's not too difficult to do so. But with leptos (and especially with themove || ....
and stuff), lifetimes are a big problem. My advice: Don't bother. Just heap allocate them all. Worst case, if your website starts to perform badly, then look into it. Don't worry about it until it does.Also, you don't have to do
String::from
everywhere. That's the good part. You can add#[prop(into)] class_names: String
and pass in a string slice, and leptos will automatically callinto
on them. So if you have multiple types that can all beInto
-ed into each other, you can pass any of them as a prop. GG.Relevant documentation: https://leptos-rs.github.io/leptos/view/03_components.html#into-props
Lesson 5:
.with
/.update
vs.set
/ .get
I was originally confused between these two options. Sure,
.with
provides a reference, and.get
does a clone, but honestly, the compiler is smart enough to optimize those things away. That shouldn't be the biggest problem (also, refer to previous point. Don't prematurely optimize).The easiest way to see it is this:
Use
.with
/.update
if you want the previous value, and use.set
/.get
if you don't.Thanks @Jinxit for the clarification
Relevant documentation: https://leptos-rs.github.io/leptos/reactivity/working_with_signals.html#getting-and-setting
Lesson 6: Weird behavior of
into
forChildren
Absolutely random thing, but if you add
#[prop(into)] children: Children
, leptos doesn't seem to like it. Might be a bug (CC @gbj), but if you're using children, just use theChildren
type. Don't bother adding aninto
for the prop.Relevant discussion: https://discord.com/channels/1031524867910148188/1133501534139846770/1134119852479610991
More to come
This discussion is intentionally left incomplete. As I go through my journey of porting my react codebase to leptos, I hope to add more to this discussion and document more things that someone else (or probably future me :p) can learn from.
Beta Was this translation helpful? Give feedback.
All reactions