Manthan Jamdagni
Manthan Jamdagni

Reputation: 1021

Using React to change content on already present page using chrome extension

I've just started learning React and was trying to create a chrome extension using it. I am trying to create an extension with a button whose onClick will highlight certain given words on a webpage. I am able to highlight words in content I am introducing to the page but not in the content already present on the page

Here is the code I have come up with -

There is a button on the popup HTML with class highlight-hazardous-words

popup.js (extensions popup):

window.onload = () => {
const $highlightHazardousButton = document.querySelector('.highlight-hazardous-words');

$highlightHazardousButton.onclick = () => {
    // Get active tab
    chrome.tabs.query({
        active: true,
        currentWindow: true,
    }, (tabs) => {
        // Send message to script file
        chrome.tabs.sendMessage(
        tabs[0].id,
        { injectApp: true },
        response => window.close()
);
});
};
};

main.js(main react app content lies here):

import React from 'react';
import ReactDOM from 'react-dom';
import Highlighter from "react-highlight-words"

class HighlightHazardous extends React.Component {
    constructor(props) {
        super(props);
        this.state = {searchWords : this.props.searchWords, textToHighlight : this.props.textToHighlight}
    }

    render() {
        return (
            <Highlighter
                highlightClassName="highlighted-text"
                searchWords = {this.state.searchWords}
                autoEscape = {true}
                textToHighlight = {document.body.innerText}
            />
        )
    }
}
// Message Listener function
chrome.runtime.onMessage.addListener((request, sender, response) => {
    // If message is injectApp
    if(request.injectApp) {
        // Inject our app to DOM and send response
        injectApp();
        response({
            startedExtension: true,
        });
    }
});

function injectApp() {
    const newDiv = document.createElement("div");
    newDiv.setAttribute("id", "chromeExtensionReactApp");
    document.body.appendChild(newDiv);
    ReactDOM.render(<HighlightHazardous searchWords={['hazardous', 'alcoholic']}/>, newDiv);
}

Here the newDiv appended has highlighted words with the whole page's body, I want to highlight hazardous or alcoholic present anywhere on any webpage and not in new div, basically, I don't want to inject this new div and change the content of the page already present.

Upvotes: 2

Views: 3212

Answers (1)

Jessica Rodriguez
Jessica Rodriguez

Reputation: 2974

The only way to access web-page's DOM content is to use Content Scripts component where Chrome Extensions use content-scripts to mention a JS and CSS file in manifest.json, that need to be injected into the underlying page.

As stated below:

The problem with our create-react-app is that the build step will generate the output JS file in different name each time (if the content changed). So we have no way to know the actual file name of the JS file, hence we can’t mention it in our manifest.json file.

The workaround for this is to eject out of create-react-app and modify the webpack configuration by hand to create a separate entry point for content script.

Sources:

Upvotes: 3

Related Questions