2

I want my Chrome Extension to interact with a page that includes some simple React components - a table in the middle of a lot of plain javascript/html.

My Extension is NOT built with React.

What script could you inject into a page, via a Chrome Extension, that could access React Elements (get their key values and similar)? A simple example would go a great way to helping me...

Here's what I've done so far:

I can inject a script and append to the body of the page...but am not sure how to "import react" or otherwise take advantage of React code on the page.

Using the React inspector in console I can see a element with rows as children.

How would I get the children of that Element? Their key values, for instance?

If I inject the following script I just get "unexpected identifier" errors:

import React from 'react';
import ReactDOM from 'react-dom';

I've tried variations (in my injected script) on the following...no React is found (I know it is there)...The "Inside FindReact function...1" message is logged but nothing else (so I know my script is injected without error).

console.log('In React script...run sub...');
reactSub();

function reactSub(){
    console.log('Inside FindReact function...1');
    window.FindReact = function(dom) {
        for (var key in dom) {
                    console.log('Loooping...');
            if (key.startsWith("__reactInternalInstance$")) {
                var compInternals = dom[key]._currentElement;
                var compWrapper = compInternals._owner;
                var comp = compWrapper._instance;
                            console.log('Inside FindReact function...2') + console.log(comp);
                return comp;
            }
            let snapCount = React.Children.toArray(this.props.children).filter((item) => item.props.className === 'criterions').length;
            // let rubricTable = FindReact(document.querySelector('.criterions'));
            console.log('Inside react script...') + console.log(snapCount);
          }
        return null;
    };

Any help/direction appreciated.

11teenth
  • 1,853
  • 1
  • 15
  • 28
  • Inspect React-Devtools extension and see how it works. I guess its content script spoofs (in the [page context](https://stackoverflow.com/a/9517879)) some standard API used by React during initialization and thus everything gets logged/remembered inside the hook so it can be used later to hack into the internal state. – wOxxOm Oct 29 '18 at 08:14
  • Can you provide some Example code? – 11teenth Oct 29 '18 at 10:16

1 Answers1

5

This post was very helpful: React - getting a component from a DOM element for debugging. Especially the answer updating for React 16.

The code I was trying had many problems...but it also (particularly var compInternals = dom[key]._currentElement;) worked only in React 15 and earlier. My target page, evidently, uses React 16.

Here's how I was able to inject a script to gain access to the React side of things:

In manifest.json:

"web_accessible_resources": [
    "scripts/yourScript.js"
],

In an existing content script (perhaps triggered by some event or the existence of your target React component):

var th = document.getElementsByTagName('body')[0];
    var s = document.createElement('script');
    s.setAttribute('type', 'text/javascript');
    // s.setAttribute('src', file);
    s.setAttribute('src', 'chrome-extension://yourChromeEXTid/scripts/yourScript.js');
    th.appendChild(s);

Then a new script, yourScript.js:

console.log('In React script...run sub...');

window.FindReact = function(el) {
  for (const key in el) {
        console.log(key);
    if (key.startsWith('__reactInternalInstance$')) {
      const fiberNode = el[key];
            console.log('fibernode: ') + console.log(fiberNode);
            return fiberNode;
      // return fiberNode && fiberNode.return && fiberNode.return.stateNode;
    }
  }
  return null;
};

var targetEl = document.querySelector('.targetReactElement');
var reactIs = FindReact(targetEl);
console.log('Result: ') + console.log(reactIs);

This at least returns, to the console, the React object...which I'm sure I can then do something useful with:)

11teenth
  • 1,853
  • 1
  • 15
  • 28