Unwrap ReactCustomWidgetWrapper

0
I want to access the loaded data store of a TreeTable widget on a page from a custom javascript. So I obtain its HTML Node, call dijit.getEnclosingWidget(domNode), but it returns an instance of 'mxui.widget.ReactCustomWidgetWrapper' , although I need an instance of react.Component. I can’t find a corresponding public member in the returned object. Is there a utility function where you pass the wrapper and get the react component? Or does ReactCustomWidgetWrapper have public members that forward the call to the wrapped component properties and methods?
asked
2 answers
0

i am not sure you are using this widget or not, but the TreeTable has an open source. You can follow the component TreeTable.tsx to achieve what you want.

https://github.com/mendixlabs/mendix-tree-table/blob/master/src/components/TreeTable.tsx

 

answered
0

The code of TreeTable on Github does not know anything of ReactCustomWidgetWrapper so I had to search elsewhere. Here is what I found:

React widgets are wrapped with dojo mxui.widget.ReactCustomWidgetWrapper
It stores no reference to the React component
Its domNode.parentNode is null
Its _markerNode property is an <!-- HTML Comment --> and is a previous sibling of the actual widget node

It's easier to skip obtaining ReactCustomWidgetWrapper and find the React Component directly from the widget DOM Node:
  FindReact(dom) // see below
Simplified:
  dom.__reactFiber$xxx.return.stateNode

Alternatively, the React Component can be found via:
  (obj as ReactCustomWidgetWrapper)._markerNode.__reactContainer$xxx.child.child.stateNode  

// https://stackoverflow.com/a/39165137/447503

 

function FindReact(dom, traverseUp = 0) {
    const key = Object.keys(dom).find(key=>{
        return key.startsWith("__reactFiber$") // react 17+
            || key.startsWith("__reactInternalInstance$"); // react <17
    });
    const domFiber = dom[key];
    if (domFiber == null) return null;

    // react <16
    if (domFiber._currentElement) {
        let compFiber = domFiber._currentElement._owner;
        for (let i = 0; i < traverseUp; i++) {
            compFiber = compFiber._currentElement._owner;
        }
        return compFiber._instance;
    }

    // react 16+
    const GetCompFiber = fiber=>{
        //return fiber._debugOwner; // this also works, but is __DEV__ only
        let parentFiber = fiber.return;
        while (typeof parentFiber.type == "string") {
            parentFiber = parentFiber.return;
        }
        return parentFiber;
    };
    let compFiber = GetCompFiber(domFiber);
    for (let i = 0; i < traverseUp; i++) {
        compFiber = GetCompFiber(compFiber);
    }
    return compFiber.stateNode;
}

 

answered