Replace DOM with JSX in React 18 - reactjs

How to remove this error message from my console
I'm using ReactDOM.render to replace certain "unreachable" parts of my code with JSX components, it worked fine in previous versions but now I'm getting this annoying error message and I want to get rid of it.
Long story:
I'm using the FullCalendar lib for react18 and Nextjs.
I'm facing a limitation from the lib, in previous versions I was able to pass JSX to render in the header buttons, but in the current version 5.11.2 it's not possible anymore, it only let you set either text or a bootstrap/font-awesome icon.
So I instead used an old known trick to replace DOM with no more than the HTML element
ReactDOM.render(
<AnyIconIWantToUse />,
window.document.querySelector("#element-to-replace-id")
)
and that is what brings up the said error message
What I've tried
As the error suggest I've tried using createRoot instead but it gives me an error too (and afaik it's meant to be used only with the root component so I prefer not to use it).

This should help you out
createPortal(
<AnyIconIWantToUse />,
document.getElementById("element-to-replace-id")
)

I ended up achieving what I wanted with another approach.
Instead of replacing DOM content directly with JSX I instead render the desired JSX into the DOM and replace the DOM with DOM
// utils/replaceDOM.ts
import type React from 'react';
import { renderToString } from 'react-dom/server';
type ReplaceDOM = (
elementToReplace: Element,
replacement: React.ReactElement
) => void;
const replaceDOM: ReplaceDOM = (elementToReplace, replacement) => {
if (!replacement) return;
// Get html from component (only get first render)
const replacementHTML = renderToString(replacement);
// Parse html string into html
const parser = new DOMParser();
const parsedDocument = parser.parseFromString(replacementHTML, 'text/html');
const replacementElement = parsedDocument.body.children[0];
// Append replacement to DOM
window.document.body.prepend(replacementElement);
// Replace children with element
elementToReplace.replaceWith(replacementElement);
};
export default replaceDOM;
Then I can use it as desired
replaceDOM(elementToReplace, <ElementIWant className="w-6" />);

Related

Create Html from React Component including Style

I have a simple react component in which using ref I am getting the div but I have to generate a html includes styling as well. So I can pass this html to PDF generation backend server.
pdfRef(elem){
console.log(elem);
//<div><span>dataPDF</span> </div>
}
render() {
return (
<div ref={(elem) => this.pdfRef(elem)} className="SomeCssClass">
<span >dataPDF</span>
</div>
);
}
}
[Edit]
When I try to print the div via ref, the elements are printed with class name. But when I send this string to pdf service, since only html element is sent and class name without the actual css , the pdf is generated without style.
is there any way to generate html with css as as string so further it can be send to pdf service. Hope the question is clear
Any pointers?
The server.js script in react-dom lets you render a React component to static html string. You can require it in your code like:
const ReactDOMServer = require('react-dom/server');
Or using ES6 syntax:
import ReactDomServer from 'react-dom/server'
After this you can render your component to HTML string using the ReactDomServer.renderToString or ReactDomServer.renderToStaticMarkup functions as follows:
const htmlStr = ReactDomServer.renderToStaticMarkup(<MyComponent prop1={'value1'} />);
This looks almost exactly like ReactDom.render, except that it doesn't need the second parameter of dom node to render at, and the html string is returned. Additionally this method can be used on both client and server side. For your generate-pdf use case renderToStaticMarkup would suffice. If required check the documentation at following link for subtle difference between the two methods mentioned above: https://reactjs.org/docs/react-dom-server.html

How can I suppress "The tag <some-tag> is unrecognized in this browser" warning in React?

I'm using elements with custom tag names in React and getting a wall of these errors. There's a GitHub issue on the subject (https://github.com/hyperfuse/react-anime/issues/33) in which someone states:
This is a new warning message in React 16. Has nothing to do with anime/react-anime and this warning can safely be ignored.
It's nice that it can be safely ignored, but it's still not going to pass scrutiny when my code is filling the console with useless error messages.
How can I suppress these warnings?
I found a potential fix for this issue - if you are using a plugin (and potentially in other circumstances) you can use the is attribute.
Found here when working with X3d - simply writing <scene is="x3d" .../> works
Update:
see the answer from #triple with the correct solution:
https://stackoverflow.com/a/55537927/1483006
Orignal:
I'm not saying this a correct thing you should really do, but you could hook console.error and filter this message by putting this somewhere before react-anime is loaded:
const realError = console.error;
console.error = (...x) => {
// debugger;
if (x[0] === 'Warning: The tag <g> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.') {
return;
}
realError(...x);
};
It seemed to work on the sample that was posted in the GitHub issue you linked at least. :3
My solution was to create envelope component which renders <div> with desired classes:
import React, {Component, DetailedHTMLFactory, HTMLAttributes} from "react";
import classNames from "classnames";
export default class SimpleTagComponent extends Component<SimplePropTypes>{
baseClassName = 'simpleComponent'
render() {
return React.createElement(
'div',
{
...this.props,
className: classNames(this.baseClassName, this.props.className),
},
this.props.children
);
}
}
type SimplePropTypes = HTMLAttributes<HTMLDivElement>
export class MyTag extends SimpleTagComponent {
baseClassName = 'my'
}
I don't believe there's a built in way to suppress the error message.
The warning message is logged right here in react-dom. You could fork react-dom and simply remove the error message. For a change as small as this, perhaps using something like patch-package would be useful, so you don't have to maintain a fork.
React 16 gives warnings with x3dom components .
including is="x3d" in component suppresses these warnings.
I had the same error. My problem was the new file for js when I use sfc I first letter of the name (tagname) has to be capital letter. I am just new so, I didn't notice it. But I am writing this just in case
I wrapped my HTML in the <svg> tag.
https://github.com/facebook/react/issues/16135:
I think you're probably rendering them outside of <svg> tags.
This is what got rid of the Web Browser Warnings for me:
BAD:
const SocialMedia = (props) => {
<socialmedia>
return (
Good:
const SocialMedia = (props) => {
return (

Error in using react-bootstrap

I'm using React-bootstrap package on my Keystone.JS project. To test I tried putting a button in my index page. However, I get the following warning:
Warning: Unknown props bsStyle, active, block, navItem,
navDropdown, bsClass on tag. Remove these props from the
element.
This is the code where I use Button:
var React = require('react');
var Layout = require('../../layouts/defaultLayout');
var ReactDOMServer = require('react-dom/server');
var Button = require('react-bootstrap').Button;
module.exports = React.createClass({
render: function () {
return (
<Button bsStyle="primary">Default button</Button>
);
}
});
What am I missing? Thanks for the help.
Long story short
Many component libraries (including react-bootstrap see issue) were relying on passing custom properties to DOM elements w/o data- prefix.
Starting 15.2.0 React warns about unknown properties on DOM element
Add warning for unknown properties on DOM elements. (#jimfb in #6800, #gm758 in #7152)
You need to update library. This was fixed in v0.30.0-rc.1.

Using Material Design Lite with React

I am trying to use MDL on an existing project that uses React, and I am running into several issues. Things seem fine on the first load, although there are many warning messages:
Warning: ReactMount: Root element has been removed from its original container. New container:
This happens pretty much for every DOM element that has a class recognized by MDL (examples: mdl-layout, mdl-layout__content, etc.) and it happens on any DOM changes.
Further, when changing routes, there is an "Invariation Violation" error:
Uncaught Error: Invariant Violation: findComponentRoot(..., .0.2.0.1.1.0.0.0.0): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser)...
Does this mean that MDL and React are pretty much incompatible?
Update: The issue disappears if the element with class="mdl-js-layout" is not the topmost element in the reactjs render function. Once I wrapped that element, all is good.
Try to wrap a DIV element outside, I just fixed that problem in this way.
If you are using Redux + React + MDL + React-Router, You can wrap a DIV element to Provider element:
import React, { createStore } from 'react';
import { Provider } from 'react-redux';
import Router, { HistoryLocation } from 'react-router';
var store = createStore();
Router.run(routes, HistoryLocation, (Handler, state) => {
React.render((
<div>
<Provider store={store}>
{
() => <Handler {...state} />
}
</Provider>
</div>
), document.body);
});
Hope it can help you :)
The first and second errors are related to each other, take a look at MDL's layout source code. I would say that the following causes the mutation of your React root element (which is the mdl-js-layout component):
var container = document.createElement('div');
container.classList.add(this.CssClasses_.CONTAINER);
this.element_.parentElement.insertBefore(container, this.element_);
this.element_.parentElement.removeChild(this.element_);
container.appendChild(this.element_);
If you take a look at the official example, you can see that MDL massively changes your markup and that is exactly what React doesn't like.
BTW: I also have composed an article which studies the combination of React with MDL.

Output object name other than React with jsx syntax

with React v0.12 the #jsx pragma is gone which means it is no longer possible to output jsx with anything other than the React.METHODNAME syntax.
For my use case I am trying to wrap the React object in another object to provide some convenience methods thus, in my component files, I want to be able to write:
var myConvenienceObject = require('React-Wrapper');
var Component = myConvenienceObject.createSpecializedClass({
render: function () {
return <div />
}
})
However the jsx compiler automatially converts <div /> into React.createElement("div", null)
With older versions of React it was possible to handle this using the pragma at the top of the file. However, since that has been removed, I was wondering if there was any way currently to change the name of the object compiled by jsx so <div /> would be transformed into myConvenienceObject.createElement("div", null)
No, it's no longer possible to use a custom prefix for JSX. If you need to do this, you'll need to modify the JSX transform code, or create a fake React.
var React = require('react'), FakeReact = Object.assign({}, React, {
createElement: function(component, props, ...children){
// ...
// eventually call the real one
return React.createElement(component, props, ...children);
}
});
module.exports = FakeReact;
And then to use it you import the fake react and call it React.
var React = require('fake-react');
// ...
render: function(){ return <div />; }
If you would like to make some elements contains in your myConvenienceObject, you could consider the children props as shown in the doc. But this may need some changes in the myConvenienceObject too, to accept the children.
By the way, i'm not sure where is this createSpecializedClass functions comes from and what it does

Resources