Hacker News new | ask | show | jobs
by jdellinger 2115 days ago
So I recently had the opportunity to use the new composition API, which will come in V3, in a project and want to share my two cents. The project had some limitations tho: no webpack and no typescript (so basically inline x-templates and pure browser JS).

Starting of with the composition API was great. No "this", easy reuse of logic via react-like "useXYZ" hooks and a general fast development. But two things really bugged me:

* You need to be really careful when passing around values and how you handle them. Destructure a Proxy object? You instantly lose reactivity. Not using a reference to proxy object in computed? Changes won't trigger the computed function. There is a lot of magic involved and while it may seem that it takes a lot of "thinking" from you, once it doesn't work you will have to rethink and maybe even ditch some of the underlying language's features.

* "ref" vs "reactive", where "ref" is used for primitives which need a proxy object wrapper and "reactive" is used for objects/arrays. Now, my primary problem is that you again have to use specific operations based on whether your using ref or reactive. A "ref" array can be easily set to an empty array via `arr.value = []`. If you try this with a "reactive" array, you will lose reactivity; you would have to use `arr.length = 0`.

TypeScript detects a lot of those pitfalls and, IMO, it is essential when using the composition API. Without it, there is too much invisible magic happening.

3 comments

I used to prefer (and by a lot) Vue more than React because of its simplicity and completeness (router + store + everything you need).

After trying to use v3 for a new project and trying out the composition API, I've gone back to React.

With v3, and the composition API, to me, it lost all of its appeal (being simple, easy and complete). Now to me it has the worst of both worlds... it's not as easy anymore, has a lot of gotchas and conceptual overhead.

The same thing happened to Meteor.js, another project with which Evan was involved. Meteor started out with an ethos of simplicity and friendly developer experience. It lost it's ethos and was picked apart in the name of "scalability". This has left people in a lurch who were drawn into Meteor for it's simplicity and now have projects to maintain in a largely abandoned framework.

I've primarily moved over to Django with server rendered content and sprinkles of JavaScript where needed.

This is the appeal of Phoenix LiveView for me. Server rendering was already incredibly fast with Phoenix, but the ability to forgo the majority of JS with LiveView bypasses all of these framework complications.
Yes, LiveView is very exciting, although I haven't used it.

For those interested in LiveView-esque functionality in other frameworks , there are some similar projects cropping up:

- Django Reactor https://github.com/edelvalle/reactor

- Laravel Livewire: https://laravel-livewire.com/

- Rails Stimulus Reflex: https://docs.stimulusreflex.com/

- Intercooler.js: https://intercoolerjs.org/

I’d be very curious if those can be implemented in a performant way.

There’s a combination of low level features that combine to make LiveView work effectively.

Woah I had no idea that existed.

Here's a great introduction to LiveView:

https://www.youtube.com/watch?v=U_Pe8Ru06fM

This one's also pretty good: https://www.youtube.com/watch?v=MZvmYaFkNJI&t=1s (Build a real-time Twitter clone in 15 minutes with LiveView and Phoenix 1.5)
> server rendered content and sprinkles of JavaScript where needed.

Nice. We need more of this.

Oh well wait until you hear about Laravel. I appreciate that there is still such a large developer community committed to pushing traditional server-rendered web apps forward. Laravel has some amazing stuff for creating presentation layers within the framework, the most exciting (to me) is Livewire
For what it's worth, LiteDOM is a nice, small (3kb) library to enhance HTML templates with a bit of declarative reactivity:

https://litedom.js.org/

Have you considered that this might be an issue on your end, and not the V3 Composition API's end?

4 year Vue dev here (right after 2.0 release). In Vue 2, you have a bunch of "magic" properties. Your state goes under the "data" key, computed properties go under "computed", methods go under... etc. Then you have the lifecycle hook magic methods: "created()", "destroyed()", etc.

In Vue 3, you have one function -- "setup()". This function returns the stuff you want to use inside of your component. This could be state/reactive data using "reactive()" or "ref()", derived data using "computed()", watchers, plain functions, whatever.

If you need to use lifecycle hooks, then you put an "onMounted(() => {})" or whatever in your "setup()".

The API was stripped down to essentially one initialization method where you set up everything you need.

Though to be fair, these days I write Vue like a weirdo and I use JSX with it.

  const App = defineComponent({
    setup() {
      const state = reactive({ count: 0, msg: "Hello" })
      const doubledCount = computed(() => state.count * 2)
      const inc = () => count.value++
      
      return () => (
        <div onClick={inc}>
          <p>{state.count}: {state.doubleCount}</p>
          <p>{state.msg}
        </div>
      )
    }
  })
This doesn't add up. None of the simplicity or completeness has changed, and the composition API is completely additive and optional. You can still use Vue exactly like you always have, with better performance and flexibility.

Do you use Hooks in React? Because in that framework, that actually is replacing the older methods, and if you use Hooks then the Composition API is the same (and better in many ways).

As far as I understand the Composition API is purely opt-in and aimed at cases where you want to trade simplicity for power/control.

The Options API is still the default and remained pretty much the same.

The composition API is opt-in, but will likely be the de facto standard if/when the majority of projects and tutorials use it.
> will likely be the de facto standard if/when the majority of projects and tutorials use it.

Why would you think that? To me it sounds like a completely unbased opinion and goes agains everything that I read in the v3 documentation or in numerous discussions.

> Possibly the biggest change is our new Composition API, which is entirely additive- the previous Options API will continue to be supported, as the Composition API is an advanced feature.

https://v3.vuejs.org/guide/migration/introduction.html

The Composition API is the last item in the API reference, the Options API is positioned much more prominently.

https://v3.vuejs.org/api/options-data.html

In the Guide, the Options API has its own section while the Composition API is nested within the "Advanced Guides" section.

https://v3.vuejs.org/guide/introduction.html

If you check the React docs most examples still do not use hooks and we know how that turned out.

https://reactjs.org/docs/state-and-lifecycle.html

Agreed. That's generally how these things are introduced. It's a shame, because Vue as it currently stands, offers impressively simple answers, to many complicated UI development questions.
I don't understand this comment. You went back to React because Vue introduced a new, entirely optional, "feature"? Why?
Yes I fully understand this. Also with vue2 you often get problems with the internal version of "array" that is wrapper around a normal array to detect changes.
How so?
At least a year or so ago, when I was still working on a Vue project, some external libraries didn't work with Vue reactivity due to the way it was implemented by overriding Array built in methods. I think we ran into this issue with some lodash functions.
Perhaps updates to the array content don't trigger reactive computations? Not sure really.
Haven't looked @ v3, but I have a question: why would the Proxy object be available to destructure? Why not use a revocable proxy that is only a proxy when it's being modified through accessors? Why would any state management library author expose a Proxy? It should expose ubiquitous, useful, human-readable, undecorated save for maybe Symbols, JSON.