React Known Issues and Workarounds

known-issues
react

#1

XD’s support for React is pretty amazing, but there are some limitations, issues, and gotchas of which you need to be aware. This thread will summarize issues with React that are known, and what kind of workarounds (if any) you can use.


pinned #2

#3

Issue

Checkboxes do not trigger change events. You can use a ref instead to assign an event handler.

Workaround

return (
    <label class="row">
        <input type="checkbox" 
               ref={el && el.addEventListener("change", e => {
                   /*…*/
               })}
        />
        <span>Check me!</span>
    </label>
);

#4

Issue

It’s not possible to supply a value to a SELECT control at this time and have it rendered as selected.

Workaround

return (
    <select value={selectedValue}
            ref={el && el.setAttribute("value", selectedValue} />
        <option value="1">Hello!</option>
        <option value="2">There!</option>
    </select>
);

#5

Starting with React 16.5, react and react-dom make use of schedule. Schedule makes use of cancelAnimationFrame (which is not available). Even after polyfills, it doesn’t work. It looks like ultimately schedule is using setTimeout. Even with the suggested polyfills for setTimeout I can’t get it to work.

For now, stay with 16.4.2 and everything works great.


#6

I worked around this differently so that the value was autoselected (and not just available in JavaScript) by creating a wrapper component.

Here’s what the component looks like:

const React = require('react');
const PropTypes = require('prop-types');

// This component exists because <select>s' default values don't work in XD.
class XdSelect extends React.Component {
    constructor() {
        super(...arguments);
        this.selectRef = React.createRef();
    }

    componentDidMount() { this._selectOptionByValue(); }
    componentDidUpdate() { this._selectOptionByValue(); }

    _selectOptionByValue() {
        const selectEl = this.selectRef.current;
        const {options, value} = this.props;
        selectEl.selectedIndex = options.findIndex(option => (
          option.value === value
        ))
    }

    render() {
        const {options, disabled, value, onChange} = this.props;
        return (
            <select ref={this.selectRef} value={value || ''} onChange={onChange} disabled={Boolean(disabled)}>
                {options.map(({value, name}) => (
                    <option key={value} value={value}>{name}</option>
                ))}
            </select>
        );
    }
}

XdSelect.propTypes = {
    options: PropTypes.arrayOf(PropTypes.shape({
        value: PropTypes.string.isRequired,
        name: PropTypes.string.isRequired
    })).isRequired,
    value: PropTypes.string.isRequired,
    onChange: PropTypes.func.isRequired,
    disabled: PropTypes.bool,
};

module.exports = XdSelect;

Here’s how to use it:

const options = [
  {
    value: 'foo',
    name: 'Hello, Foo'
  },
  {
    value: 'world',
    name: 'Hello, World'
  }
];

return <XdSelect
  options={options}
  value='world'
  onChange={myOnSelectChangeFn}
  disabled={false} />

This worked well for my purposes. Feel free to modify it as needed!


#7

This thread should be listed in the DOCs. I spent ages in trying to fix the select box issue, and did not figure out, why it did not work, until I came across this post.

If there are known issues, and there are, link this Thread… :slight_smile: