Opt-In reactivity for createEffect instead of opt-out #1803
lunafoxfire
started this conversation in
Ideas
Replies: 2 comments 1 reply
-
Sounds reasonable its just a shortcut that combines |
Beta Was this translation helpful? Give feedback.
0 replies
-
If you want to react to a specific event, why don’t you simply use an event listener instead of an effect? In this example, you can do the |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
My Concern
First off I wanna say Solid has been a joy to use. Compared to React I really enjoy the simplicity of the API and how much easier it is to get things done. However I wanna talk a bit about my number one source of bugs so far: createEffect. So 99% of the time that I'm using createEffect, it is to react to changes in one specific prop or piece of state, and execute some side effect when that happens. Take this UI pattern for example:
![Screenshot_1](https://private-user-images.githubusercontent.com/21229800/252046520-15e00c6c-2b83-455d-aa39-64c12510b966.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0MTU1OTcsIm5iZiI6MTczOTQxNTI5NywicGF0aCI6Ii8yMTIyOTgwMC8yNTIwNDY1MjAtMTVlMDBjNmMtMmI4My00NTVkLWFhMzktNjRjMTI1MTBiOTY2LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTMlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjEzVDAyNTQ1N1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTNiODViYzUyZDQ5N2ZlNzc1MTAzZWQwMDhlMGY3YzFmODNlYWIxY2UyZjI0ZDQzZWFhZDM4MmVhYmYxZTQxY2YmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.eLlU0J0sxNv2msa0xQE-2C0weOE5kWaqeP8ux2WPYFw)
If I want to react to the user selecting a new option from the dropdown I might do something like this:
However if I later decide that I want to use some other data in that effect, I might change the code to something like this:
But now I have a bug! Any time I update the description text, an alert will now be triggered, even though that was not my intention. And a situation like this could obviously be much more complicated and easy to miss. My options in this case are to use
on
oruntrack
. Imo, untrack is the worse option since I would rather be explicit and list the dependencies precisely:This is fine, however this is very noisy syntactically (in my opinion) in order to accomplish what I feel like (in my opinion) should be the default mode of operation for createEffect. And the noise gets amplified when you consider that props must be specified as
() => props.foo
in theon
deps. Again, any time I am using createEffect I am thinking in terms of reacting to changes in props or state. Withouton
, createEffect has the potential to become very complicated and react to very unclear dependencies. In my code I have gotten in the habit of usingon
almost every time except for the most trivial uses.A Solution
So it is probably not reasonable to change the signature and functionality of createEffect. In my code I have created a helper function to combine
createEffect
andon
:Which is used like so:
I have been using this helper to the complete exclusion of createEffect and I feel like it does a much better job of keeping my side effects easy to reason about. It may not seem like a big deal when I could just use
createEffect
andon
together to achieve the same thing, but having a single primitive means that it is easy for me to do the correct (in my opinion) thing and always specify effect dependencies.Note Vs React
So I get that the decision to remove dependency arrays from Solid was probably inspired by annoyance with React. I think this totally makes sense for things like createMemo, which is obviously much nicer when reactivity is opt-out rather than opt-in. However, I think with React, the useEffect dependency array isn't an annoyance in concept. In theory, the dependency array provides a critical way to see at-a-glance what causes the code to execute, which is extremely important when dealing with non-pure side effects. For pure computations like useMemo, 99% of the time you don't actually care what changes cause re-computation -- you just always want the computed value up-to-date.
However, in practice React's useEffect dependencies become cluttered with junk you don't care about due to React's rerender model. Stuff like callbacks that need to be up-to-date and
prevValue
for detecting deltas. So much so that there is an entire linter rule dedicated to making sure you don't forget dependencies, and you must specifically opt out of this rule on a case-by-case basis. Basically React's useEffect pretends to be opt-in but it is opt-out in practice. Solid doesn't have this problem, and createEffect dependencies can be specified minimally (viaon
) to describe exactly what triggers an effect. But again, Solid hides this behindon
.Conclusion
Personally, I think opting in to side effects makes way more sense both from a conceptual and maintainability point of view. createEffect has the potential to generate an immense amount of complexity if dependencies are not explicitly defined. I believe it should absolutely be standard practice to always specify effect dependencies since it can become very difficult to understand what an effect's auto-generated dependencies are, especially as the effect becomes more complex. However, I am not satisfied with the current method of doing this in Solid. Having
on
as a separate primitive both makes the syntax more noisy and signals to the developer that explicit dependencies should be the exception rather than the rule.Ultimately I would rather createEffect itself directly support explicit dependencies to make it crystal clear that explicit dependencies are allowed/preferred. However, changing the API of createEffect so drastically is understandably probably not an option at this point. Instead, adding
useEffectOn
or some equivalent to the API would also be a good option imo. I want effects with explicit dependencies to be a first-class citizen within Solid in order to promote code that is both easier to read and write across the whole community and not just those that spend way too much time thinking about it (cough).Mostly I would like to hear the thoughts of other developers on these points. As Solid grows in popularity I can forsee this potentially
becoming one of the small nagging things people start to dislike about it. Which would be a shame because I love Solid and will continue to use it!
Thank you for reading my essay
Beta Was this translation helpful? Give feedback.
All reactions