<sp-radio-group> React issues – onChange vs. onInput vs. onClick

UPDATE #1: added info about onInput events

Hi,
I’ve noticed that in a React environment <sp-radio-group> is a bit weird.

<sp-radio-group>
  <sp-label slot="label">Select filetype</sp-label>
  <sp-radio checked value="png8">PNG</sp-radio>
  <sp-radio value="png24">PNG-24</sp-radio>
  <sp-radio value="jpg">JPG</sp-radio>
</sp-radio-group>

While in Vanilla JS onChange is quite fine, here it doesn’t do a thing.

// onChange in React is not working
<sp-radio-group onChange={(evt) => console.log("Changed", evt)}>
  <sp-label slot="label">Select filetype</sp-label>
  <sp-radio checked value="png8">PNG</sp-radio>
  <sp-radio value="png24">PNG-24</sp-radio>
  <sp-radio value="jpg">JPG</sp-radio>
</sp-radio-group>

Conversely, onInput fires 2 events at the same time:

// onInput in React fires 2 events
<sp-radio-group onInput={(evt) => console.log("Changed", evt)}>
  <sp-label slot="label">Select filetype</sp-label>
  <sp-radio checked value="png8">PNG</sp-radio>
  <sp-radio value="png24">PNG-24</sp-radio>
  <sp-radio value="jpg">JPG</sp-radio>
</sp-radio-group>

UPDATE: the 2 events are regarding the currently selected radio and the previously selected one. Problem is that the last event that fires is related to the previously selected radio, hence I can’t just let run the handler twice because in the end it’ll “run right”—it won’t.

Finally, onClick seems to work, but when e.g. a label is present, the clickable area (below in gray) is way bigger than the radio buttons, hence false clicks (that don’t produce any real change) can trigger the handler

// onClick in React when there's a label expands the "clickable area" too much
<sp-radio-group onClick={(evt) => console.log("Changed", evt)} style={{backgroundColor: "gray"}}>
  <sp-label slot="label">Select filetype</sp-label>
  <sp-radio checked value="png8">PNG</sp-radio>
  <sp-radio value="png24">PNG-24</sp-radio>
  <sp-radio value="jpg">JPG</sp-radio>
</sp-radio-group>

In the screenshot below I clicked in random places of the gray area without selecting a radio.

Is there any reason why React doesn’t like the simple onChange here? Should I use a wrapper component?
Thanks!

Davide

Yeah, this is some strange handling by React. React won’t wire up certain events like change automatically for controls that look like web components (which sp-radio-group et al look like), which means that to listen for it properly you’ll need to wrap it (the WC component in the samples works fine here).

For onInput and onClick, it does seem that React will wire up those events (I’m not sure why it makes an exception here), but as you’ve noticed, you get notifications for everything underneath, and further onClick is being fired whenever you click anywhere in the sp-radio-group (expected, since the user did click within its bounds).

It does appear that if you use evt.currentTarget.value, you’ll see the correct value (even though the handler fires multiple times). If you’re just treating this as a controlled element, that may be fine. If you’re doing a lot of work each time the handler is called, that might be a problem.

In general, though, the most straightforward way to mix React & Spectrum UXP is to use a wrapper like WC and handle the events there.

2 Likes