5 ms·
I absolutely despise writing any kind of GUI/graphics/layout code in React's clunky long-form declarative style, but for whatever reason it's really starting to
by dvt 6y ago
I absolutely despise writing any kind of GUI/graphics/layout code in React's clunky long-form declarative style, but for whatever reason it's really starting to take off. I guess it's a sign of the times: there are developers these days that have quite literally grown up on React. It's starting to feel like XML (used everywhere, even when it might not make much sense).
But to me, the code is longer, more unwieldly, more prone to error, and to top it off, it also inherits all of React's annoying idiosyncrasies. It's weird to even type this out, but Java's Swing felt more intuitive than seeing D3 on top of React.
For example:
<circle
cx="150"
cy="77"
r="40"
/>
Just the fact that this could technically be written as draw.circle(150, 77, 40) in any sane programming language should give you some pause.
- thitcanh 6y agoYour example really does not help your cause. What’s 150? No idea, gotta look into the docs. The “insane” SVG example is much more readable, its JSX version would actually even maintain types (cx={150} since it’s a number). I generally agree with the rest of your comment, but that’s just a bad way to show your point.
- ggregoire 6y agoI tend to agree with you about the "JSX used everywhere", I hate plain logic wrapped inside a component that doesn't render anything but is still designed to be called in a render() (think something like <Fetch url={url} />). It doesn't seem that common anymore, but people used to do it just because it was technically possible, although it didn't make any sense. But the example you chose doesn't shock me that much. Why do you think draw.circle(150, 77, 40) is saner and more intuitive than <Circle cx="150" cy="77" r="40" />? It's fine to me if it renders a <svg> inside its parent node. Also the named parameters on the second function is a great addition for code clarity.
- genericstorage3 6y agoI'm the opposite, I despise anything angular, vue, knockout, that makes devs learn a new language. React just uses js, almost plain.
- brailsafe 6y agoThat's a bit dramatic and inaccurate don't you think? Angular maybe comes closest to your definition of new language, but the rest is pretty much HTML with an @ sprinkled in. We've been using the same paradigm of double curly braces and such for quite a while. React may use more or less js, but I find it more mentally taxing to render or parse what is better expressed as HTML in a template. Outside of that, unless you've already been working with react a lot, the syntax of how data flows together is certainly not any more intuitive than Vue.
- Tade0 6y agoBut JSX is a whole new language on top of HTML and JS. Otherwise you would have to write lengthy, nested createComponent calls.
- dsego 6y agoJust JS? What are those angled brackets in JS exactly?
- scotty79 6y ago> this could technically be written as draw.circle(150, 77, 40) No. It couldn't be. Because circle is an element of a tree so you'd have to pass in the parent node.
- somethingAlex 6y agoCompared to the seemingly arbitrarily split js files filled with jQuery at other large projects I've worked on, I'd take a declaratively described component per-file React app any day. I remember trying to find the class for the element I'm manipulating imperatively in jQuery in an equally arbitrary CSS file only to realize almost none of those attributes are applied cause some other more specific selector in another file took precedence. That's obviously due to poor organization, but at least React is readable with HTML, JS, and CSS all right next to each other with very clear intent due to the declarative style.
- dsego 6y ago> component per-file React app Nothing in React requires to have one component per file. And you can do the same with jQuery or vanilla JS. > equally arbitrary CSS file Something makes programmers, who are usually very opinionated about their code architecture & patterns, to just throw it all away and just pile on shitty css code. It's almost as if they don't actually put any thought into it. Could it be that their Java code patterns just cargo-culting and they don't truly understand it? That can't be it, something else? > React is readable with HTML, JS, and CSS all right next to each other React has JSX, not HTML. And nothing requires CSS to be in the same component or file. It's still just an organizational issue.
- somethingAlex 6y agoI'm not speaking strictly, I'm simply alluding to the fact that it's very easy to organize React projects such that its obvious which HTML the JS and CSS is scoped to. Pragmatically, I have not found that to be the case in projects which use jQuery.
- jacobolus 6y agoWhat does SVG's syntax for circles have to do with React?
- Chris_Newton 6y agoJust the fact that this could technically be written as draw.circle(150, 77, 40) in any sane programming language should give you some pause. This is comparing apples and oranges, though. Your example only uses the required properties that any circle will have. Once you start adding details like strokes and fills, you will probably need extra function calls in the imperative case. Those function calls will probably update some hidden state that defines the style for whatever is drawn afterwards, which means you’re going to have to either keep track of that implicit state if you want it to apply to multiple things you’re drawing or reset it after each drawing call. If you do want to manipulate a group of related elements collectively, for example to transform or style a certain part of your image as a group rather than adjusting the drawing for each element individually, the React/SVG version allows you to specify those properties and their scope explicitly by applying them to a common parent element, and everything stays clearly structured and can be examined in browser dev tools. The equivalent with an imperative drawing library will probably require individual adjustments for the parameters to each drawing command, or again some sort of implicit state that needs to be managed. If you want to apply more complex effects, possibly to a group of related elements, the declarative version lets you attach a powerful filter as easily as a fill colour. Again, this means the browser is doing the heavy lifting of working out how to apply the effect it specifies to whatever that combination of elements originally looks like, instead of having to deal with potentially complicated dependencies manually while drawing imperatively. If you want any sort of interactivity with the elements in your image, with the React/SVG version you can attach event handlers and let the browser work out which events should be sent where. With imperative drawing code, you’re probably going to have to manage any interactions yourself, including reinventing all the hit testing logic you get for free with the browser. I’m not going to argue that there’s no place for imperative graphics libraries or anything silly like that, but there are plenty of reasons you might prefer a declarative interface depending on what you need to do. Ironically, I would argue that the advantages a declarative style offers when it’s a good fit are much the same as you listed in your comment: the code typically ends up shorter, clearer, and less error-prone.
- sfvisser 6y agoAll of the above can be done with a super clean declarative interface using functions/methods without JSX. JSX vs normal JS code has nothing to do with imperative vs declarative.
- ironmagma 6y agoSome people really want to make a living off complaining about modern frontend. > for whatever reason it's really starting to take off React is ten years old, so it's done more than start. There's a reason people prefer declarative over imperative, which is that it represents the intention of the programmer. The declarative approach can have its backend (implementation) tweaked to the nth degree and still the description (the declaration) will remain constant, and that's what we as humans want -- separation between the request ("I want X drawn") and the fulfillment ("draw two lines, one here one there") of said request. This is why there's also SwiftUI and things like QML. > draw.circle(150, 77, 40) Not only does that lack any kind of description of the order (is it radius, position, or position, radius?), but it isn't extensible if we later want to add more functionality (after all there are a lot of aspects of how you could draw a circle, including transparency). If you opt for putting those in different calls, like Processing, now you have (an implicit) state to deal with, and we know what happens with state -- it becomes a problem. So much so that languages like Clojure were invented specifically because state causes so many bugs.
- darepublic 6y agoThere is plenty of state going on in the react code and yes on the surface you just have a nice clean render declaration. But when you start to want to express complicated animations but insist on doing things by the React Bible (ie no dirty refs) it can easily become worse than the imperative solution with performance degradation s and difficult to understand code that is deceptive ly simple but leaves a lot of complexity poorly expressed. Even in this article itself ,which takes great pains to hype up the react way or the highway, the manner it handles exit animations in React shows that the abstraction is already leaking.
- ironmagma 6y agoNormally, if you are writing something so weird that it needs to be imperative to be readable or work right, you can just do that inside a useEffect, or at least encapsulate it in a component. For most animations, ReactCSSTransitionGroup is sufficient. This is an interesting case study only because D3 is particular about wanting data to be stored in the DOM, and React is particular about wanting the data to be stored anywhere but the DOM. I am curious though what you mean by dirty refs?
- gherkinnn 6y agoJSX allows your version too. <Circle draw={[150, 77, 40]} /> It's a bit hideous, yes. But it illustrates the point: most people prefer what are effectively named parameters. // alternative interface <Circle draw={{ cx: 150, cy: 77, r: 40 }} /> Since all three are of the same type and potentially within the same order of magnitude, there's no way to discern what the values represent. In any case, you're free to pass an entire collection at once: // individual props <Circle {...props} /> // pass all options in one prop <Circle draw={props} />
- itronitron 6y agoBut with React you can now define your UI using four distinct file types and syntaxes instead of only three (or one if you are using Java Swing.)