8
votes

I'm using React useRef with Flow typings and I'm trying to write a wrapper component for a third party web components library.

The web component expects a changeCallback function and I'm using the ref to assign it to the ref.

function RadioButtonGroup({ onChange, children }) {
    const ref: { current: null | ElementRef<ElementType> = React.useRef(null);

    React.useEffect(() => {
        if (ref.current) ref.current.changeCallback = onChange;
    }, [onChange]);

    return <web-component ref={ref}>{children}</web-component>
}

Since HTMLElement does not contain a property called changeCallback flow throws an error.

Cannot assign handleChange to ref.current.changeCallback because property changeCallback is missing in HTMLElement

I tried extending "ElementType" with the property like this

ElementRef<ElementType & { changeCallback: Function }>

But this results in the following error:

Cannot instantiate ElementRef because object type [1] is not a React component.

The web component does not fire the "change" event on change. It executes the function changeCallback. Here's the documentation for the library.

// MyComponent.js

class MyComponent extends Component {

    constructor() {
        // ...

        // Create a ref
        this.sdxSelectEl = React.createRef();
    }

    componentDidMount() {
        // Attach callback here to ref
        this.sdxSelectEl.selectCallback = (selection) => console.log(selection);
    }

    render() {
        // ...
        <sdx-select ref={el => (this.sdxSelectEl = el)} />
        // ...
    }
}
2

2 Answers

5
votes

The solution is to call useRef with an explicit type argument to represent the expected type:

const ref = React.useRef<null | (HTMLElement & { changeCallback: Function })>(null);
0
votes

I believe you need to use addEventListener to attach the callback to a web component:

if (ref.current) ref.current.addEventListener('change', onChange);