Modify React App in Chrome Extension - javascript

I have built a Chrome extension that modifies a React app client side. So far I was able to
1) inject React and ReactDom from development branch
let injc=(src,cbk) => { let script = document.createElement('script');script.src = src;document.getElementsByTagName('head')[0].appendChild(script);script.onload=()=>cbk() }
injc("https://unpkg.com/react#16/umd/react.development.js",() => injc("https://unpkg.com/react-dom#16/umd/react-dom.development.js",() => { console.log("Hello")}))
ReactDOM.render('<Hello name="World" />', document.getElementById('container'));
see here for more info about this code injection.
2) I have used the HTMLReactParser that transforms HTML to React Component in order to get my html outer html node contents and turn into a React Element:
var reactObj=HTMLReactParser(node.outerHTML);
ReactDOM.render(reactObj, this.textarea);
This seems to work fine, preventing and any React rendering issues due to the mutation of the React code i.e. it actually edit the React components. It also prevents the error Uncaught Error: Minified exception occurred; use the non-minified dev environment when using non development react libraries.
See here for other attempts about mutating React components in a Chrome Extension.
3) That said, now I'm trying to apply a text overlay to the actual text nodes in the React app using the library TextOverlay, but despite of some success and some bug fix I had on that library, I cannot get rid of this. See here for more details about this specific integration issue.
This is the example code. Given a React app with some text, I try to apply a text overlay on that like here:
Currently the results is not what is expected, since the overlay is partially applied:
Example Code Repo: chrome-extension-react-app

Related

Accessing React component displayName in HTML

How can I access a rendered React component's displayName property in HTML? There seems to be some way to do it given React DevTools, but I've been reading through the source code for that package and can't figure out how they're doing it. I recognize that this might be cross-referenced from the associated JS file, but I'm hopeful that's not the case.
Context: I have a script that identifies certain components in the prod version of our app and adds a red border around them, which works fine. In React DevTools I can see the displayNames of those components even on prod (they're not minified for whatever reason, which is beyond my scope of curiosity right now). I'd love to be able to surface those displayNames in addition to the added border.

Markdown-to-jsx not accepting source

I am using one of the Material UI templates for blog posts: https://github.com/mui-org/material-ui/tree/master/docs/src/pages/getting-started/templates/blog.
I created my React app with npx create-react-app.
When I console log the source it comes out as a string, when I add it in the markdown-to-jsx it shows me this error index.module.js:1 Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_0_react___default(...) is not a function.
Steps to reproduce:
create an app with npx create-react-app
import the material UI template written on the above link
use fetch(post1).then(res => res.text()).then(text=>setMarkdown(text)) inside a useEffect hook to get the markdown text.
Add the markdown state in the way that the template used it here
<Markdown className={classes.markdown} key={markdown.substring(0, 40)}>
{markdown}
</Markdown>
and the error happens
Thanks in advance for any help you can give me.
What I have tried basically boils down to changing the MD file to a js string export default, changing markdown-to-jsx versions, and trying different attribute options on the markdown-to-jsx library but none is working and I am lost.

Can I use a React app as a component on a static HTML page

I'm new to React and JS, and working with react-csv-viewer.
It works as expected and I can build and deploy it on a local server. But I do not require this, I just want to integrate the app as a component of a static HTML page.
I've tried following the process listed on the React tutorial for this, but I have trouble understanding the build process and how can I achieve this.
All I wish to achieve is to be able to use <CsvViewer /> provided by the author, possibly like this
const rootElement = document.getElementById("root");
ReactDOM.render(<CsvViewer />, rootElement);
and get the viewer app rendered at my HTML file, without building and deploying the viewer app on a (local) server.
Will appreciate any help or hints in this regard.
You can add React as it was shown in the tutorial you linked. The downside is that, you can't use JSX syntax (as it should be converted to JS during build time as it's not recognized by browsers as so).
Here is a post explaining how you can do so without transpilaton steps.
https://codepen.io/alexkrolick/post/react-without-a-build-step
Alias React.createElement, and call it to create components.
e.g.)
const h = createElement // convenient alias
// Instead of
<div className="foo" />
// create an element like so
h("div", { className: "foo" })
For more info on how that works, check out the official documentation.
https://reactjs.org/docs/introducing-jsx.html#jsx-represents-objects
But I really doubt anyone writes React code that way without a transpilation step in real life.
Would creating a separate site/page with React be a problem by chance? You can check out ParcelJS to easily create a React site if you aren't familiar with transpilation.

Using an external React component on Rails application

I am trying to use the rc-slider React component on a existing Rails application that is using react-rails gem and it already have some other components that were built within the application that work just fine.
Based on this blog post I've been able to follow its first 3 steps, I've found the minified and browser-ready version of it here, added the file to the suggested path and required it on the application.js as recommended but even seeing the code within the Sprockets generated application javascript file that is rendered on the browser I can't see or use the supposed global variable it would provide according to step 4.
In the component's examples page it uses a const Slider = require('rc-slider'); statement in order to get that available. I've tried that but without luck as it throws: Uncaught ReferenceError: require is not defined. The same happens when I try the README usage's section approach: import Slider, { Range } from 'rc-slider';. I've tried both from an existing JS where I load other React components and also from the browser's Dev Tools Console window.
Am I using the wrong approach to the problem or maybe missing/overseeing any concept or basics here?
If you want to use Sprockets, you can get a pre-compiled version of rc-slider from unpkg:
https://unpkg.com/rc-slider#6.0.0/dist/rc-slider.js
Taking a look at the source, I see it exports the library as rc-slider:
So you can access it as window["rc-slider"] and use it from there, for example:
var RCSlider = window["rc-slider"]
var container = document.getElementById("container")
ReactDOM.render(
<div>
<RCSlider />
<RCSlider.Range />
</div>,
container
);
jsfiddle
That way, if you put rc-slider.js in the asset pipeline, you can use RCSlider in your javascripts.

How can one tell the version of React running at runtime in the browser?

Is there a way to know the runtime version of React in the browser?
React.version is what you are looking for.
It is undocumented though (as far as I know) so it may not be a stable feature (i.e. though unlikely, it may disappear or change in future releases).
Example with React imported as a script
const REACT_VERSION = React.version;
let root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<div>React version: {REACT_VERSION}</div>
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Example with React imported as a module
import { version } from 'react';
console.log(version);
Obviously, if you import React as a module, it won't be in the global scope. The above code is intended to be bundled with the rest of your app, e.g. using webpack. It will virtually never work if used in a browser's console (it is using bare imports).
This second approach is the recommended one. Most websites will use it. create-react-app does this (it's using webpack behind the scene). In this case, React is encapsulated and is generally not accessible at all outside the bundle (e.g. in a browser's console).
From the command line:
npm view react version
npm view react-native version
With the React Devtools installed you can run this from the browser console:
__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.forEach(r => console.log(`${r.rendererPackageName}: ${r.version}`))
Which outputs something like:
react-dom: 16.12.0
Open Chrome Dev Tools or equivalent and run require('React').version in the console.
That works on websites like Facebook as well to find out what version they are using.
It is not certain that any global ECMAScript variables have been exported and html/css does not necessarily indicate React. So look in the .js.
Method 1: Look in ECMAScript:
The version number is exported by both modules react-dom and react but those names are often removed by bundling and the version hidden inside an execution context that cannot be accessed. A clever break point may reveal the value directly, or you can search the ECMAScript:
Load the Web page (you can try https://www.instagram.com they’re total Coolaiders)
Open Chrome Developer Tools on Sources tab (control+shift+i or command+shift+i)
Dev tools open on the Sources tab
In the very right of the top menu bar, click the vertical ellipsis and select search all files
In he search box down on left type FIRED in capital letters, clear the checkbox Ignore case, type Enter
One or more matches appear below. The version is an export very close to the search string looking like version: "16.0.0"
If the version number is not immediately visible: double click a line that begins with a line number
ECMAScript appears in the middle pane
If the version number is not immediately visible: click the two braces at bottom left of the ECMAScript pane {}
ECMAScript is reformatted and easier to read
If the version number is not immediately visible: scroll up and down a few lines to find it or try another search key
If the code is not minified, search for ReactVersion
There should be 2 hits with the same value
If the code is minified, search for either SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED or react-dom
Or search for the likely version string itself: "15. or "16. or even "0.15
Method 2: Use a DOM breakpoint:
Load the page rendered by React
Right click a React element (anything, like an input field or a box) and select Inspect Element
Chrome Developer Tools displays the Elements pane
As high up in the tree as possible from the selected element, but no higher than the React root element (often a div directly inside body with id root: <div id="root">), right click an element and select Break On… - subtree modifications
Note: It is possible to compare contents of the Elements tab (DOM current state) with the response for the same resouce on the Networks tab. This may reveal React’s root element
Reload the page by clicking Reload left of the address bar
Chrome Developer Tools stops at the breakpoint and displays the Sources pane
In the rightmost pane, examine the Call Stack sub-pane
As far down the call stack as possible, there should be a render entry, this is ReactDOM.render
Click the line below render, ie. the code that invokes render
The middle pane now displays ECMAScript with an expression containing .render highlighted
Hover the mouse cursor over the object used to invoke render, is. the react-dom module exports object
if the code line goes: Object(u.render)(…, hover over the u
A tooltip window is displayed containing version: "15.6.2", ie. all values exported by react-dom
The version is also injected into React dev tools, but as far as I know not displayed anywhere.
First Install React dev tools if not installed and then use the run below code in the browser console :
__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.get(1).version
If you have the React DevTools extension enabled, you can execute this in the console:
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.get(1).version
Here's the output if I execute it on my website in production (nikolovlazar.com)
In an existing project a simple way to see the React version is to go to a render method of any component and add:
<p>{React.version}</p>
This assumes you import React like this: import React from 'react'
Open the console, then run window.React.version.
This worked for me in Safari and Chrome while upgrading from 0.12.2 to 16.2.0.
You can either run the following command(s) on your terminal, depending if you are using npm or yarn:
npm view react version
or
yarn view react version
Or You can also open your package.json file in your project under the "dependencies" check "react": after the semicolon will be the version of your react
For an app created with create-react-app I managed to see the version:
Open Chrome Dev Tools / Firefox Dev Tools,
Search and open main.XXXXXXXX.js file where XXXXXXXX is a builds hash /could be different,
Optional: format source by clicking on the {} to show the formatted source,
Search as text inside the source for react-dom,
in Chrome was found: "react-dom": "^16.4.0",
in Firefox was found: 'react-dom': '^16.4.0'
The app was deployed without source map.
In index.js file, simply replace App component with "React.version".
E.g.
ReactDOM.render(React.version, document.getElementById('root'));
I have checked this with React v16.8.1
This strategy should work all of the time: In the end React has to be included in a js file in the html through a script tag. So find that file and look for the React version.
Look through all the scripts included in the HTML (view source)
One of the links include the script to React. WebPack lumps the libraries together under a common-xxxx.js file
Open that script file and ctrl + f search for React
Presto, version number there
If you have already deployed your app which used webpack. You can use the below step to identify the "react" and "react-dom".
Open DeveloperTool in your browser
Go to Source Tab
Check your appName.js file
Search for "react" or "react-dom"
You will find something like below. That will be the version your react-app is using.
"webpack/sharing/consume/default/react/react?1aa9": () => (loadStrictVersionCheckFallback("default", "react", [,[1,17,0,0],[1,16,8,0],1],// ..SOMETHINNG
"webpack/sharing/consume/default/react-dom/react-dom?8d07": () => (loadStrictVersionCheckFallback("default", "react-dom", [,[1,17,0,0],[1,16,8,0],1], // ..SOMETHINNG
OR
register("react-dom", "17.0.2", () // ..SOMETHING
register("react", "17.0.2", ()// ..SOMETHINNG
Note: It only applicable for deployed app
Use the command line commands for checking the version of the ReactJS. You can run the below command.
npm view react version
or
yarn view react version
console.log(React.version) will print the version of the react running in your project.
To know the react version, Open package.json file in root folder, search the keywork react. You will see like "react": "^16.4.0",

Categories

Resources