Tuesday, October 13 2015 9:07 PM

Do we need (a discussion about) jQuery?

Author: matthias - Last modified: Tuesday, October 13 2015 9:35 PM

en jquery  javascript  react comment  opinion

Discussions about the role of jQuery bubble up these days. Paradigms change, not at least triggered by concepts (re-)introduced with React, Flux and redux. Should we try to avoid jQuery and direct DOM manipulation if possible? I'm not sure, but I want to share some thoughts I had reading a thread titled "Stop say You Don't Need jQuery" in the JS group of linked.in.

No doubt jQuery helped all of us in rapidly developing beautiful cross-browser UI features. No doubt either that it's pretty easy to write messed up code with jQuery, especially when your project is about to grow quickly... It's a question of time & budget, developer skills, performance considerations and of course your individual project needs: Every situation needs the right technologies, patterns, tools, libraries, frameworks, "sandbox areas" and ideas of how all of this can stay maintainable and subject to be refactored frequently. Always keep in mind that a growing codebase is hard to test if it's "hacked"!

If some of your project needs are perfectly covered by specific jQuery plugins – is it okay to start developing with that now? I think: Yes. If criteria stated above is fulfilled.

Think of an application/project you start developing using jQuery today. My advices:

  • Write code that people can quickly understand, that you understand when returning to it one year later.
  • Use either a well supported framework with a bright community or even write Vanilla JS, but add structure by following some architecture pattern.
  • Separate concerns, don't leave people alone with $.callback(hell) spaghetti code!
  • Let $.magic() only do the magic!

Then, maybe in 2016, there's this absolutely cool way of integrating and developing rich UI features by just using that awesome new "React Declarative Decorator Dynamite" ES2016 mixin style stuff... You'd probably like to move your code base towards it without rewriting everything, right? You don't? Ah, come on, then just write down jQuery code like it comes to your mind... ;-)

By the way: Did I mention React? Ever tried Flux or even redux?

Kidding.

Partly.

Comment / Share »
Wednesday, April 8 2015 9:17 PM

React hates me: "Overcontrolled" components

Author: matthias - Last modified: Wednesday, April 8 2015 9:54 PM

en javascript  react flux  state  checkbox  dom  html  events  prevendefault

More accurately: The DOM hates me. I'm currently hacking a lot of React (with fun) and thought that strictly bypassing the default handlers for user input element onChange events in favor for a fully controlled value flow through React components' state and props might be a good idea. Actually, it is not.


Abstract and advice for the impatient: Don't build React "controlled components" in conjunction with preventDefault() in event handlers listening to onChange (which wraps onKeyUp/Down...) events. Silly idea.


Controlled Components

If you found your way to this post, you're potentially in some similar situation to the one I tried to summarize above: You're using React Forms with Controlled Components and for whatever reason you want to take over full control for every type of user input, typically listening to the React wrapped onChange event (good idea!) and preventing default behavior by calling preventDefault() (bad idea!) – meaning that you also have to take care of setting the state of appropriate properties which in turn update the input fields as soon as the render() method is automatically called on state value changes.

Stressing React/Flux

If you're still think this sounds like a somewhat curious approach, you're right. Anyhow, let me just give a short explanation of my motivation: I'm stressing the concept of React/Flux that way that I even want the state of user input fields to be reflected in a related store – and vice-versa. Therefore dispatched actions that update the stores' properties which values flow back through change events emitted thereafter for eventually updating the DOM sounded like a good idea to me. Yes, give me full control over every user input and create a keystroke state! Well, just an idea. Unfortunately not one of my best.

A code fragment to illustrate the situation:

var TestForm = React.createClass({

  getInitialState: function() {
    return {
      message: 'Hello!'
    };
  },

  handleValueChange: function(e) {
    e.preventDefault();
    // Here I'm calling some Flux style action (creator) which in turn
    // emits a change event and updates the components' state
    this.actions.sendMessageToTheWorldViaFluxStore(e.target.value);
    // (instead of directly reflecting the value via this.state:)
    //this.setState({ message: e.target.value });
  },

  render: function() {
    return (
      <div>
          <input 
              type="text"
              onChange={this.handleValueChange} 
              value={this.state.message} />
      </div>
    );
  }
});

Problems...

Basically this approach seems to be possible and behave like expected when using e.g. standard text input fields. You can catch the current value, store or manipulate it and finally assign the value to a state variable. But you'll face two major problems soon, both not directly related to React but to the nature of HTML elements and the DOM, namely:

Checkboxes (and Radio Buttons): Manually updating state fails for checkboxes (and without having tested it: I think for radio controls as well). Why? The problem one will face is that the checkbox onChange event behaves in a special way since the era of HTML (how could I forget!): You may not toggle the state of a checkbox manually via the .checked property. Nor does React. The onChange (onClick) event is fired after the element state changed internally. This may just be reverted based on the return value of the event handler. See this post for a comprehensive examination of this fact.

Performance: It seems to be reasonably fast to capture the user input events for immediately assigning the values back to the state variable, so that the Virtual DOM updates and eventually tiny parts of the actual DOM is re-rendered. But as soon as those values go a longer way through JavaScript objects, event listeners and further manipulation, it significantly slows down Browser performance and kills UX (noticeable lag during typing!).

... and the solution.

"But don't you see", you may say, "that you must not use preventDefault() and just go on like you want with all that Flux crap! State may be updated and reflected (delayed) either way." Yes, absolutely. Call me an idiot. Let the browser do its very basic jobs. (But... unfortunately then it cannot be guaranteed that the captured input fields actually reflect the state of my store... what about race conditions when updating... uhh... ouch! ... Well, who the f--- cares!)

Here's a React fiddle dealing with that stuff.

Comment / Share »