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.
JSX vs normal JS code has nothing to do with imperative vs declarative.
<circle cx="150" cy="77" r="40" />
and draw.circle(150, 77, 40)
is that the former uses named parameters and the latter does not, and I suspect a lot of us would consider the former to be the more explicit, less error-prone choice in that case.I generally agree with the rest of your comment, but that’s just a bad way to show your point.
> 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.
oh I guess that is confusing, I just meant to invoke the attitude of react purists to using refs (like in the article), although imo it is sometimes the best and 'cleanest' way of expressing what you want to do
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.
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.
No. It couldn't be. Because circle is an element of a tree so you'd have to pass in the parent node.
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.
<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} />React just uses js, almost plain.
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:
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.