React indeterminate

By  on  

I've fallen in love with React.js and JSX over the years; state-based rendering and a logical workflow have made me see the light of this modern framework. That doesn't mean I don't sometimes get a bit frustrated that the "simple" things seem harder than they should be. Getting a reference to an element and modifying its properties used to be simple but now you have to take into account you don't usually have element references -- you need to think in a different way. I learned this when I needed to set a checkbox's inderterminate property, a property not recognized via an attribute, one that requires a handle on the element and setting a property directly.

To add the indeterminate property to the checkbox, I needed to take advantage of the ref attribute:

const { value, checked, indeterminate } = this.props

return render(
    <input
        type="checkbox"
        value={value}
        checked={checked}
        ref={el => el && (el.indeterminate = indeterminate)}
    />
)

Since the ref is run on each render, the indeterminate property is updated appropriately, and thus the checkbox appears as expected.

Regardless of how amazing your framework appears, there's always a blind spot that requires a bit of a hack to accomplish what's expected. That's what a framework does, though: gives you 99% of what you need and makes the 1% difficult!

Recent Features

  • By
    Vibration API

    Many of the new APIs provided to us by browser vendors are more targeted toward the mobile user than the desktop user.  One of those simple APIs the Vibration API.  The Vibration API allows developers to direct the device, using JavaScript, to vibrate in...

  • By
    How I Stopped WordPress Comment Spam

    I love almost every part of being a tech blogger:  learning, preaching, bantering, researching.  The one part about blogging that I absolutely loathe:  dealing with SPAM comments.  For the past two years, my blog has registered 8,000+ SPAM comments per day.  PER DAY.  Bloating my database...

Incredible Demos

  • By
    :valid, :invalid, and :required CSS Pseudo Classes

    Let's be honest, form validation with JavaScript can be a real bitch.  On a real basic level, however, it's not that bad.  HTML5 has jumped in to some extent, providing a few attributes to allow us to mark fields as required or only valid if matching...

  • By
    Fullscreen API

    As we move toward more true web applications, our JavaScript APIs are doing their best to keep up.  One very simple but useful new JavaScript API is the Fullscreen API.  The Fullscreen API provides a programmatic way to request fullscreen display from the user, and exit...

Discussion

  1. BryanYang

    the last words are exactly. there is always something we miss when we design a framework. so the best way is to optimize again and again.

  2. > Since the ref is run on each render, the indeterminate property is updated appropriately, and thus the checkbox appears as expected.

    This is kind of true but it’s probably not working how you imagined in your head. The ref doesn’t actually get run each render, only when the component mounts/unmounts or the function passed to ref changes.

    In your example since you’re using an anonymous function this looks like a new function every time the component re-renders and so React will call it again. If you were to replace that ref with a function that doesn’t change every render (e.g ref={ this.setCheckboxRef }, this example would no longer work.

    This is the exact scenario described in the caveats section of the docs here: https://reactjs.org/docs/refs-and-the-dom.html#caveats-with-callback-refs

    Instead you want to assign the ref to a class property and listen to prop changes in componentDidUpdate and proxy them to the checkbox (if you’re using a class component) or use the new useEffect API in hooks.

  3. “gives you 99% of what you need and makes the 1% difficult!” This 1% never covers in any update…

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!