4

So HTML has this awkward problem that to make label work with input, they need to be linked by a matching id/for (renamed by React to htmlFor) pair.

Here's some simplified code with change handles, etc., skipped:

class CheckboxComponent extends Component {
    render() {
      let {selected,name,idkey} = this.props;
      let id = `checkbox-${idkey}`;
      return <div>
        <input type="checkbox" id={id} checked={selected}/>
        <label htmlFor={id}>{name}</label>
      </div>;
  }
}

Is there any reasonable way to generate those IDs? There are some options but all of them seem really awkward:

  • Pass unique idkey all the way - but that means not just this component but every parent, grandparent, etc., using it now needs a unique idkey.
  • Use Math.random() to generate them - that makes render() non-deterministic, which feels wrong.
  • Generate a random key with Math.random() when component gets created/mounted, so render() itself would be deterministic.
  • Just turn that whole container into <label> and rewrite the CSS a bit to make it work.
  • Give that <label> no for at all, instead some kind of onClick handler to find sibling <input> with DOM API... That's quite straightforward in jQuery-based code, but quite a bit of a mess in React.

Is one of these solutions actually standard practice? Am I missing something else better?

0xCursor
  • 2,242
  • 4
  • 15
  • 33
taw
  • 18,110
  • 15
  • 57
  • 76
  • This is hard to tell without any information about the nature of the data to be selected. If there is a corresponding database entity in your backend you can use that id. If the checkbox ist statically rendered you can just use an appropiate string. Last resort would be to use a library for generating a uuid. Don't use `Math.random()`! – trixn Jul 29 '18 at 00:36
  • It's a smart form without database backing, the whole form just exposes some calculations.Checkboxes could probably get unique ids within form, but then whole form would need some unique key which would need to be passed many levels down, since I'd like multiple copies of the form to be displayed on same page for comparison purposes. – taw Jul 29 '18 at 00:41
  • If there are multiple forms then also give them ids and dynamically derive the input id from the form id like `${formID}-round-values-checkbox` or whatever the checkbox is there for in a template string. – trixn Jul 29 '18 at 00:45
  • Related: [How to generate unique IDs for form labels in React?](https://stackoverflow.com/q/55505554) - for hooks see https://stackoverflow.com/a/55505554/568458 – user56reinstatemonica8 Apr 07 '20 at 09:47

1 Answers1

2

According to your comment, it seems like id can be any random number.
You can use a library called short-id just to generate random IDs.

It has an option to configure how ID is generated but in your case it doesn't seem to matter

import shortid from 'short-id'

class CheckboxComponent extends Component {
    render() {
      let {selected,name,idkey} = this.props;
      let id = shortid.generate();
      return <div>
        <input type="checkbox" id={id} checked={selected}/>
        <label htmlFor={id}>{name}</label>
      </div>;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
dance2die
  • 35,807
  • 39
  • 131
  • 194