Getting Invalid Hook Call Warning when trying to integrate React with exiting web application
Tags: help, react, reacthooks
Published: 2022-12-06 05:33:51

We have a web application that is built using JSP pages. We are trying to migrate UI to React. Migration needs to be incremental as it's a huge application and we cannot migrate it completely in one go.

We are trying to run a poc to see how we will integrate react components in phased manner. We are able to integrate a vanilla react component (a static Select) following this [React Docs page](https://beta.reactjs.org/learn/add-react-to-a-website).

Problem comes when we started using useState hook. We started to get "Invalid Hook Call Warning".

We created a react app and created components there, it works as react application. We converted JSX components to plain JS using Babel cli (steps as mentioned on the React Doc Page).

Next we loaded React and React-DOM in the application through script tag as suggested on the page, except that we downloaded the script and referred from the file system.

```
<script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossorigin></script>
<script type="text/javascript" src="<path to component JS>"></script>
```

When we tried to load the Select component in the target DIV element, we got the hook warning.

I extracted code into a sample html

```
<html>
    <head>
        <title>My Page</title>
    </head>
    <body>
        <h1>Try React</h1>
        <div id="targetDiv">
            <h5>Place content here</h5>
        </div>
        <script type="text/javascript" src="./react/react.development.js"></script>
        <script type="text/javascript" src="./react/react-dom.development.js"></script>
        <script type="text/javascript" src="./react/components/core/coreSelect.js"></script>
        <script type="text/javascript">
            function getSelectOptions() {
                const options = [];
                options.push({ text: "Select...", value: "" });
                options.push({ text: "Arizona", value: "AZ" });
                options.push({ text: "Canada", value: "CA" });
                options.push({ text: "Europe", value: "EU" });
                options.push({ text: "Hawai", value: "HW" });
                options.push({ text: "Mexico", value: "MX" });
                options.push({ text: "New York", value: "NY" });
                return options;
            };
            let selectArgs = {id:"mySelect", name: "mySelect", options: getSelectOptions(), value: "CA"};
            let root = document.getElementById('targetDiv');
            console.log({root});
            ReactDOM.createRoot(root).render(Select(selectArgs));
        </script>
    </body>
</html>

```
Following is the content of coreSelect.js


```
var _slicedToArray = function () { 
    function sliceIterator(arr, i) { 
        var _arr = []; 
        var _n = true; 
        var _d = false; 
        var _e = undefined;
        try { 
            for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { 
                _arr.push(_s.value); 
                if (i && _arr.length === i) 
                    break; 
            } 
        } catch (err) { 
            _d = true; _e = err; 
        } finally { 
            try { 
                if (!_n && _i["return"]) 
                    _i["return"](); 
            } finally { 
                if (_d) throw _e; 
            } 
        } 
        return _arr; 
    }
    return function (arr, i) { 
        if (Array.isArray(arr)) { return arr; } 
        else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } 
        else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } 
    }; 
}();


function Select(_ref4) {
    var id = _ref4.id,
        name = _ref4.name,
        value = _ref4.value,
        options = _ref4.options;
        
    var optArray = options ? options : [{ text: 'Select', value: '' }];

    console.log("Before useState7", {useState});
    var _useState7 = React.useState(options ? options : [{ text: 'Select', value: '' }]),
        _useState8 = _slicedToArray(_useState7, 2),
        optArray = _useState8[0],
        setOptArray = _useState8[1];

    console.log("Before useState9");
    var _useState9 = React.useState(value),
        _useState10 = _slicedToArray(_useState9, 2),
        selectedVal = _useState10[0],
        setSelectedVal = _useState10[1];

    console.log("Before useState11");
    var _useState11 = React.useState(""),
        _useState12 = _slicedToArray(_useState11, 2),
        effectiveClasses = _useState12[0],
        setEffectiveClasses = _useState12[1];

    var disabled = options && options.length > 0 ? false : true;
    var onFocusClass = "active";

    function processOnClick() {
        if (!effectiveClasses || effectiveClasses.search(onFocusClass) < 0) {
            setEffectiveClasses(function (prevClasses) {
                var newClasses = (prevClasses ? prevClasses.trim() + " " : "") + onFocusClass;
                return newClasses;
            });
        } else {
            setEffectiveClasses(function (prevClasses) {
                var newClasses = prevClasses.replace(onFocusClass).trim();
                return newClasses;
            });
        }
    }

    return React.createElement(
        "select",
//        { id: id, name: name, className: "active", defaultValue: value, onClick: processOnClick, disabled: disabled },
        { id: id, name: name, className: effectiveClasses, defaultValue: selectedVal, onClick: processOnClick, disabled: disabled },
        optArray && optArray.map(function (opt) {
            var optValue = opt.value;
            var optText = opt.text;
            return React.createElement(
                "option",
                { key: optValue, value: optValue },
                optText
            );
        })
    );
};

```

I have modified the JS file as generated from babel cli to not use imports/exports. I have verified on browser console that React, ReactDOM and Select component are available.

As an experiment I tried to run the command

```
ReactDOM.createRoot(document.getElementById('targetDiv')).render(Select({id:"mySelect", name: "mySelect", options: getSelectOptions(), value: "CA"}));

```
from browser console and I still got the react hook error.

I have been trying to search internet to find a solution but all available posts work with npm and try to resolve issues with react version mismatch, but I could not find any that would discuss problem with react integration with existing non-react applications.

Any help in this regard would be greatly appreciated.