6 ms·
I would do this identically in React. const doThing = event => { const input = event.target input.value = value input.focus() sound.
by ng12 7y ago
I 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.
- lhorie 7y agoSure, if you're using a ref and being careful not to bind `value` in JSX, you're fine. That's not what you were doing though. Here's a simplified demo showing a variation of the issue: https://codesandbox.io/s/react-example-bytg0 https://codesandbox.io/s/react-example-bytg0 As for controlled/uncontrolled inputs and refs/hooks: that's kinda my point. In order to declaratively wire things up in an idiomatic way in React, we've had to introduce a bunch of React APIs to the snippet just to express the equivalent of a "when you click me, focus that guy" action -> effect relationship, because otherwise that relationship is hard to express in terms of declarative state snapshots.
- ng12 7y agoYou've misspelled the handler, onClick is the correct casing. Fix that and it works. Also you don't need to use a ref -- if I were inclined I could have grabbed the element by a query selector. I'm not sure why I would though, as I mentioned using ref is better protection against DOM updates. > In order to declaratively wire things up in an idiomatic way in React, we've had to introduce a bunch of React APIs Yes, because declarative programming is the benefit not the cost. As I said, you don't have to do it declaratively -- you can always use built-in DOM APIs -- but most people in the front-end community have agreed that doing things declaratively and architecting a UI as a state machine instead of a giant tree of independently mutating bits is preferable. One of the biggest sources of bugs in jQuery projects is developers forgetting to keep the DOM in sync with the data. The benefit of doing things declaratively is you don't have to worry about it. Cutting that problem off at the source is an invaluable benefit.
- jonahx 7y agoHe knows. He's the author of https://mithril.js.org/ https://mithril.js.org/. It's a person well-steeped in the theory and benefits of declarative and functional programming taking a step back and looking at the supposed enemy with fresh eyes and a deeper perspective.
- sergeykish 7y agoSimple and clean, almost like DOM Level 0 <input id=input /> <button onclick=' input.value = "value"; input.focus(); sound.play(); ' > Button </button>
- pailhead 7y agoWhere does `input` even come from in your code? That's invalid syntax. Was it supposed to be `const foo = input =>{...}`? b) It's kind of a bad practice to mutate raw DOM elements programatically without react, if it leads to horrible spaghetti code further down the road
- orange8 7y agoconst doThing = event => {} function doThing( event ){} Why does everyone seem to be using the first format? Isn't the second version a lot more readable/pretty? Even worse is when doThing is immediately exported and not refferenced anywhere else, but still there is this need to assign it to a const.
- ng12 7y agoArrow functions help save you from `this` insanity.
- orange8 7y agoI agree, but do all functions use 'this'?
- ng12 7y agoNo, and part of the reasoning is to explicitly avoid the chance you might accidentally refer to the wrong `this`. There's an ESLint rule to enforce this: it will complain if you use a `function` without referring to the prototype this. Makes it handy because if I do use `function` I know it's because there's a reason -- e.g. some libraries still make heavy use of the local this. https://eslint.org/docs/rules/prefer-arrow-callback https://eslint.org/docs/rules/prefer-arrow-callback
- orange8 7y agoThe rule you link to is specific to "function expressions", which may or may not use 'this'. To ask the same question differently, what about functions that do not need 'this'?
- ng12 7y agoI'm not sure what your proposal is -- use functions that use prototype this or no this, and arrow functions for ones that use contextual this? It's easier to use arrow functions for everything except for the tiny minority of cases where you want prototype this.