6 ms·
> how do you conditionally wrap some elements in another element ? You use a dynamic component: <component :is="condition ? 'WrappedComponent' : 'Unwrapp
by BiteCode_dev 5y ago
> how do you conditionally wrap some elements in another element ?
You use a dynamic component:
<component :is="condition ? 'WrappedComponent' : 'UnwrappedComponent"></component>
> That is a general theme, I've found - compared to React, Vue makes the easy things easier, but the hard things harder.
While react make the easy things annoying. It took me an afternoon to be productive with vue, several weeks with react.
And all that for what?
Having the privilege to "just use javascript"? Here is "just javascript" in jsx:
{items.map((items) => (
{display && <SomeElement
onClick={e => e.preventDefault() && foo()}
className="`${active ? 'current' : ''}`" />}
))}
Here is the same in vue template:
<SomeElement
v-for="item in items"
v-if="display"
@click.prevent="foo()"
:class="{'current': active}" />
Not only the react blob is impossible to scan, but it will be different depending of the dev who coded it, because there is no enforced patterns. You must use brain power to parse every single template line. HTML, that thing that was simple and declarative, now becomes complicated and imperative.
And that's not even weird or unusual code. That's regular stuff one writes all the time. Don't get me started on state management or spaghetti hooks.
I have yet to work on a react code base I was more productive than on a vue one. And the gaps get wider if the team is not composed of excellent coders, because react code by junior is a nightmare.
- johtso 5y agoWell, the fact that you're "just using javascript" in jsx does also mean that you need to format things nicely to avoid having an unreadable mess. Using a code formatter like Prettier helps a lot. The "react blob" is less of a blob if nicely indented. Admittedly due to the nature of Vue syntax, it's harder to make a mess because everything is just key/value.. but then you have to learn an API to express things in that way. I enjoy the fact that you don't have that layer/step with react. I definitely feel that the 3rd party classnames package should be built into React, I agree that out of the box conditional class names look a mess. I don't have enough experience with either library yet to form an opinion on which I prefer, but I definitely appreciate not having the mental overhead of remembering the vue api. I'd rather have a bit of code that's more explicit/"just javascript" than have to think "what's that symbol I need to use again?". Definitely a personal preference thing though! {items.map((item) => item.display && ( <SomeElement onClick={(e) => e.preventDefault() && foo()} className={classNames({'current': item.active})} /> ) )}
- BiteCode_dev 5y agoThat's still a blob, just a longer one, with an additional dependency and more parenthesis to mess up. It's a compromise, not an improvement. And in the end, I still have to read 2 JS expressions before even figure out what DOM element I'm actually dealing with. Then I still have to evaluate what the heck is happening in onClick and className. I still have to parse code in my presentational layer, code that is interleaved with my template indentation so it also makes it hard to understand hierarchy and easy to make mistakes. Of course, the elephant in the room we are not talking about with react is that all those things compounds. When you have 5 of such blobs in your render functions, issues don't add up, they multiply. Then you add the store system on top of it, with actions, reducers and all that fun stuff.
- mmgutz 5y agoVue has vuex, so there's a need for actions and reducers. React state has become much simpler with packages like zustand and it works wonderfully with typescript. It's not really that big of a deal to have another import. Vue's directive's (not sure if that's the correct term) are a mix bag of magic strings that tie to functions somehow. Why can't they just be a function variable like in React? The answer of course is there are smart people and smart users behind both projects and those are the trade-offs we tolerate.
- johtso 5y agoBeing so functional and playing so nicely with typescript was the main reason I swayed to react rather than vuejs. The whole ecosystem of state management does feel like a bit of a wild west.. but I guess that's often the feeling with javascript. I ended up settling with easy-peasy, which I think has similar aims to zustand. Definitely appreciate that it uses immer out of the box as that seems like a very sensible default way to go.
- BiteCode_dev 5y agoVuex is vastly less necessary for vue projects than redux for react projects. I've been coding in react and vue for years, it's not even on the same planet: before Vuex we never even needed a store, just import a component, that's your model. But even so, Vuex way better integrated, requires less boilerplate (thanks vue reactivity) than redux, or even zustand, which once you add immer, looks like blobbing all over again. Honestly, we should do a contest. Take 10 juniors out of school give them a twitter clone to write, 5 in Vue, 5 in React, and come back in a week. In fact, no need for them to be junior. Let's just take your regular Java dev. Not your 10X HN dev. Just average Joe. See how it goes.
- mmgutz 5y agoTo be fair, most of use `classnames` and likely have a higher order function for prevent import cn from 'classnames' const prevent = fn => e => e.preventDefault() && fn() // don't forget key {items.map(item => display && <SomeElement key="" onClick={prevent(foo)} className={cn(current: active)} /> )}
- BiteCode_dev 5y agoCongrats, you are reinventing part of VueJS, in a non standard, untested, undocumented, less readable way. But wait, you need another lambda to pass arguments to foo() should it change. And another wrapper for stopPropagation. And so on, and so on. And now you have to install and manage deps, import them, while your blob is still less readable because you have maps+lambda+&& to understand before even reaching what DOM element you are manipulating. The premise of React is that composing primitives is better than having a high level tool to do the job: it's supposed to be more generic, more flexible, easier to learn. In in my experience, it's true only in the case you don't have a well defined problem. But with frontend UI, we do. We know very well the problem to solve. Give me helpers. Give me wrappers. That's the only case where I welcome a DSL. I don't want to have to think in functions and workflow in my template.
- mmgutz 5y agoChanging the lambda? `onClick={prevent(() => newLambda(what, ever)}}`
- scq 5y ago> <component :is="condition ? 'WrappedComponent' : 'UnwrappedComponent"></component> That requires you to create 2 new components (which unlike React, will need to be in separate files if you're using SFCs) and pass down all the props another layer. In the end, I got around it by implementing a "passthrough" component so that you can then do <component :is="condition ? 'Wrapper' : 'passthrough'>...</component> but that is far from ideal. > Not only the react blob is impossible to scan Formatted properly, I don't really find the React example any harder to read. Your Vue example puts v-for and v-if on the same element, which is confusing - which is evaluated first? (IIRC, the answer depends on which version of Vue you are using). > it will be different depending of the dev who coded it, because there is no enforced patterns That applies to the rest of your codebase too, though. It's up to your team to decide on patterns and enforce them through linting, code review, and automatic formatting. Also, both of your examples are missing `key`, though React will warn you about it and Vue will not.
- ROARosen 5y ago> Also, both of your examples are missing `key`, though React will warn you about it and Vue will not Vue will warn when you're missing a key on the loop. >That requires you to create 2 new components (which unlike React, will need to be in separate files if you're using SFCs) Your components don't need to be in separate files even when using SFC's. Given 'component' can be as simple as adding to any Vue Component or SFC (when adding it to parent component option): <script> const myComponent = { props: ['myProps'], template: ` <div></div> ` } </script>