Search code examples
reactjsgoogle-chromegoogle-chrome-extensionbrowser-extension

ReactJS Render issue for Browser Extension Content Scripts on Chrome


I have made a browser extension which injects an iframe into the DOM that has some html in it. I have been trying to render a React component into the iframe, but it won't render and I receive the following error Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

I've tried rendering to both the iframe and even straight to the DOM via content scripts, but I still keep getting the same problem. I know the component's render function is being called, because I placed a console.log in it and it displays the message; I have also debugged it and the breakpoints stop in the render function. In addition I added the lifecycle methods componentWillUpdate and componentDidUpdate and they are not even called.

//Index.jsx
import React from "react";
import ReactDOM from "react-dom";

class Index extends React.Component{
  constructor(props){
    super(props);
  }

  componentWillUpdate(){
    console.log('componentWillUpdate');
  }

  componentDidUpdate(){
    console.log('componentDidUpdate');
  }

  render() {
    console.log('render');
    return <div>Hello!</div>;
  }
}

ReactDOM.render(<Index/>, document.getElementById("g-root"))

// Including this code to show how I was adding the react component to the DOM if it is loaded immediately via manifest.json
// const app = document.createElement('div');
// app.id = "g-root";
// document.body.appendChild(app);
// ReactDOM.render(<Index />, app);

//webpack.config
const path = require('path');

module.exports = (env, args) => {
  return {
    mode,
    devtool,
    entry: {
      react: path.join(__dirname, './Index.jsx')
    },
    module: {
      rules: [{
        test: /\.jsx$/,        
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['env', 'react', 'es2015']
          }
        }
      }]
    },
    output: {
      path: path.join(__dirname, './'),
      filename: 'react.bundle.js'
    }
  }
};
<!--This gets loaded into the iframe-->
<!DOCTYPE html>
<html>
  <head>  
  </head>

  <body>
    <div id="g-root"></div>
    <script src="react/react.bundle.js"></script>
  </body>
</html>
//manifest.json *included just to show that it has the same issue on page load.

{
"content_scripts":
  [{
  "js":["react/react.bundle.js"],
  "run_at": "document_end",
  "matches": ["<all_urls>"]
  }]
}

It should be noted that injecting the iframe, and the extension as a whole, worked fine until I started trying to add React to the project.


Solution

  • Turns out it was an issue with an internal library having to do with rendering web components with my React components.