I am making a Chrome Extension and I want to inject HTML into the page DOM using the content scripts. That is easy, but I also want the content script to be a React component and the JS itself does not need to interact with the page JavaScript context, so that makes it simpler. I have a simple way to inject a container element into the DOM that my React code can render to, but I feel like it is very hacky and so I was wondering if there was an official way that React developers could suggest (Google was not particularly useful on this specific matter).
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
render() {
return <h1>App was injected.</h1>
}
};
let container = document.createElement('div');
container.setAttribute("id", "app-wrapper");
document.body.appendChild($el);
ReactDOM.render(
<App/>, container);
I am making a Chrome Extension and I want to inject HTML into the page DOM using the content scripts. That is easy, but I also want the content script to be a React component and the JS itself does not need to interact with the page JavaScript context, so that makes it simpler. I have a simple way to inject a container element into the DOM that my React code can render to, but I feel like it is very hacky and so I was wondering if there was an official way that React developers could suggest (Google was not particularly useful on this specific matter).
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
render() {
return <h1>App was injected.</h1>
}
};
let container = document.createElement('div');
container.setAttribute("id", "app-wrapper");
document.body.appendChild($el);
ReactDOM.render(
<App/>, container);
Share
Improve this question
edited Oct 15, 2018 at 18:45
user3661841
asked Apr 13, 2016 at 12:58
user3661841user3661841
4481 gold badge3 silver badges13 bronze badges
5
|
3 Answers
Reset to default 5This solution is based on: https://github.com/yosevu/react-content-script .
Inside App.js
:
import React from 'react';
function App() {
return (
<>
<h1>Hello World</h1>
</>
)
}
export default App;
Inside content.js
:
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App'
const body = document.querySelector('body')
const app = document.createElement('div')
app.id = 'react-root'
if (body) {
body.prepend(app)
}
const container = document.getElementById('react-root');
const root = createRoot(container);
root.render(<App/>) // Render react component
Result:
I've found there's broadly two ways to do it. Both involve creating a new element somewhere in the <body>
and attaching the ReactDom.render
call to it.
- Using content scripts - but this can be a headache for React (ejecting create-react-app and managing webpack)
- Injecting the code directly from the Background.js script when a tab is active. To do this you can use
chrome.tabs.executeScript
. There is a short blog on it here: https://dev.to/anobjectisa/build-a-chrome-extension-using-reactjs-38o7
Usually it's split into 2 files, one HTML and one JS. Something like this:
index.html
<head>
<script src="path/to/bundle.js"></script>
</head>
<body>
<div id="app-wrapper" />
</body>
App.js
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
render() {
return <h1>App was injected.</h1>
}
};
ReactDOM.render(
<App/>, document.getElementById("app-wrapper"));
I don't know about an official way, but this is the implementation found in create-react-app
and most of tutorials around.
ReactDOM.render
requires an element to render to other thandocument.body
, so you create the element via DOM API. Seems pretty straightforward to me. – Pavlo Commented Apr 13, 2016 at 13:02