7 ms·
Sometimes I question if people claiming vanilla is spaghetti have actually used vanilla in any meaningful way or if they are just parroting what others have sai
by lhorie 7y ago
Sometimes I question if people claiming vanilla is spaghetti have actually used vanilla in any meaningful way or if they are just parroting what others have said. I find that a lot of times, it's the latter...
For example, something that I've come to find cumbersome about frameworks is that expressing things in terms of states makes it more convoluted to express mutations. For example: in vanilla, one sensible unit of organization would be something like this:
const doThing => {
input.value = value;
input.focus();
sound.play();
}
button.onclick = doThing
Expressing `input.value = value` is what frameworks generally shine at, but expressing the method calls is usually clunky, since they represent effects and those can't really be expressed in terms of state snapshots. So, expressing them in a "frameworky" way usually just looks like some variation of this, but on top of some abstraction (think, e.g. React's useEffect nested anonymous functions + refs + probably context and a provider because you're not going to just initialize your sound manager in your component, right?).
I think frameworks are about colocating things in some specific way, and whether the colocation structure is "good" is largely a matter of herd acceptance. W/ older frameworks like Backbone and Angular, the focus was on colocating things to fit a MVC paradigm. And people were totally on board with that. With Redux, one colocates actions for a particular piece of state. And people sing their praises about this structure too.
With reaonably written vanilla JS, it's not that there's no colocation. One colocates mutations related to a single action. It may not be a "cool kid" organization structure, but it _is_ structure.
Of course, one can write bad vanilla JS, but that's also true about any framework.
- bernawil 7y agoDid you mean something like this? const doThing = event => { input.value = event.value; input.focus(); sound.play(); } button.onclick = doThing
- deleted 7y ago[deleted]
- ng12 7y agoI would do this identically in React. const doThing = event => { const input = event.target input.value = value input.focus() sound.play() } ... <button onClick={doThing} />
- lhorie 7y agoa) that doesn't do the same thing (button != input) b) in React, it's extremely bad practice to mutate raw DOM elements programmatically (the idiomatic version is to use some state management mechanism and bind the value via `<input value={value} />`, which incidentally would be broken by this code) c) setState may be asynchronous, so you can run into nasty surprises (e.g. you can't focus a hidden element). Whereas in vanilla code, unhiding logic could be added in a predictable procedural and explicit manner, in React a naive call to .focus() in the event handler may noop because of React-rendering-pipeline-specific reasons and then we need to get into its more obscure APIs to fix it)
- ng12 7y agoAh, your code sample was incomplete so I was extrapolating. I'm assuming the complete code would be: const input = React.useRef(null); return ( <> <input ref={input} /> <button onClick={event => { input.current.value = "value"; input.current.focus(); sound.play(); }} > Button </button> </> ); Which is almost identical to how you would do it in vanilla JavaScript except you would grab input by a query selector and be less resilient against DOM mutation and your references becoming stale. To point b there's nothing wrong with having an uncontrolled input. React allows you to use the raw DOM API if you'd like. You only need to use controlled inputs if they buy you something, and then the rewrite is a small diff: const input = React.useRef(null); const [inputValue, setInputValue] = React.useState("") return ( <> <input ref={input} value={inputValue} /> <button onClick={event => { setInputValue("value"); input.current.focus(); sound.play(); }} > Button </button> </> ); This is adding a line of code (useState) but in this case it's buying you something -- you have full control of the value and are insulated against DOM updates. For point c I'm not sure what you're referring to. I can't think of a situation where React would drop your call to `input.focus()` on the floor. I just tried breaking it by spamming state updates and was unable to. The whole point of React is that it handles DOM updates seamlessly and I would be surprised if it didn't in this case.