How can I render object HTMLDivElement in my react component? - javascript

I have this code(its part from a bigger class but the relevant parts are here)
what I try to do is to take an existing div('#qr') that has a QR code that we got from Third Party and make some changes if needed after some checks.
I got this error:
invariant.js:42 Uncaught (in promise) Error: Objects are not valid as a React child (found: [object HTMLDivElement]). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of...
I'm looking for a way to render object HTMLDivElement in my react class.
the relevant code looks like this:
getQrCode() {
const qrCodeElem = document.querySelector('#qr');
const uri = encodeURI('some specific url');
if (qrCodeElem && qrCodeElem.childNodes.length === 0) {
return new QRCode(qrCodeElem, {
text: uri
});
}
return qrCodeElem;
}
render() {
return (
<div>
<div id="qr"></div>
{this.getQrCode()}
</div>
);
}

We can not insert DOM elements directly , you can use ref attribute to get reference to the parent element and insert your node after componentDidMount
getQrCode() {
const qrCodeElem = document.querySelector('#qr');
const uri = encodeURI('some specific url');
if (qrCodeElem && qrCodeElem.childNodes.length === 0) {
return new QRCode(qrCodeElem, {
text: uri
});
}
return qrCodeElem;
}
componentDidMount () {
this.qrCodeContainer.appendChild(this.getQrCode());
}
render() {
return (
<div ref={node => this.qrCodeContainer = node}>
<div id="qr"></div>
</div>
);
}

Your function is returning multiple dom nodes. Wrap them with additional tag (div, span, ...) or use fragments:
<>{this.getQrCode()}</>

Related

render a part JSX by another function component - reactJS

I have a function component like that
function myMainComponent() {
const MyUIA() {
//some calulations about attrs
return (<div><ComponentA {...attrs}></div>)
}
const MyUIB() {
//some calulations about attrs
return (<div><ComponentA {...attrs}></div>)
}
// Way A
/*
return (
<div>
<MyUIA/>
<MyUIB/>
</div>);
*/
// Way B
return (
<div>
{MyUIA()}
{MyUIB()}
</div>);
}
The results of render by WayA and WayB is the same, but in first case there is a flickering
So why the WayB has better performance without flickering ?
What is the best way to render part of renders thas exist in the same function component ?
does WayA and WayB have a specific name for example "render by calling native method" and "render by calling JSX method" in react ?
Since as we know every code we write in react is converted into JSX first, then it get rendered so if we see for native method the JSX element is created twice while for JSX it's created only once. So this is the case one can see the flickering. I hope it helps.
function myMainComponent() {
const MyUIA = () => {
return /*#__PURE__*/React.createElement("div", null,/*#__PURE__*/React.createElement(ComponentA, null)); };
const MyUIB = () => {
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(ComponentA, null));};
// Way A
return /*#__PURE__*/React.createElement("div", null,
/*#__PURE__*/React.createElement(MyUIA, null),
/*#__PURE__*/React.createElement(MyUIB, null));
// Way B
return /*#__PURE__*/React.createElement("div", null, MyUIA(), MyUIB());
}

Render HTML DOM Node in React Component

I am using Wordpress as my CMS and creating some of the pages in React and rendering it. I have a use case where i need to render HTML DOM Node inside of my React Component. I am getting the DOM Node with the help of querySelector() which returns me the DOM node. In React i am trying to render it using React.createElement. But it renders as [object HTMLDivElement] on my page.
render() {
const { reactPages } = this.props;
const innerPages = React.createElement('div', {id: "myDiv"}, `${reactPages.children[0]}`);
return (
<div className="react-cmp-container">
<h3>React Container</h3>
{ innerPages }
</div>
)
}
}
The other thing i tried was using the dangerouslySetInnerHTML:
rawMarkUp = () => {
const { reactPages } = this.props;
return {__html: reactPages}
}
render() {
const innerPages = React.createElement('div', {id: "myDiv"}, )
return (
<div className="react-cmp-particle-container">
<h3>React Particle Container</h3>
<div dangerouslySetInnerHTML={this.rawMarkUp()}></div>
</div>
)
}
This is the type of DOM Node that i am getting and passing it as props to my Component.
This is not recommended to to. It might cause many kinds of trouble later. Anyway, ...
querySelector() returns a DOM-element (or collection of such).
1. React.createElement
React.createElement does not work, because it expects another React.Element, or a string, not a DOM-element.
2. dangerouslySetInnerHTML
dangerouslySetInnerHTML does not work, because it expects a HTML string, not a DOM-element.
You could use domElement.innerHTML and put the HTML string into dangerouslySetInnerHTML, but that might not represent the DOM element as you want it.
3. useRef
You could add a ref to some element that is rendered by React. This gives you access to the corresponding DOM-element (rendered by React), and you can inject your DOM-element (returned by querySelector()) using normal DOM methods.
This disables React to "track what's going on", and you might experience inconsistent state and hard-to-understand bugs.
e.g.:
export const StaticHtml = (props)=>{
const ref = useRef();
useEffect(() =>{
var elm = document.getElementById('some-static-html');
ref.current.appendChild(elm);
}, []);
return (<div ref={ ref }>
some div
</div>);
};

Declaring text to a variable shows Text string must be rendered within a <Text> component

I have a React Native app where i'm mapping an array and assigning a text to a variable. But this throws the red screen showing 'Text string must be rendered within a Text component'. Here's where the error is throwing:
export default class index extends PureComponent {
render() {
const { payments } = this.props;
const filteredPaymentList = this.props.payments
const filteredPaymentList = payments.filter(item => {
if (item.id === 'stripe') {
item.id = 'stripe_connect';
}
return typeof Config.Payments[item.id] !== 'undefined';
});
return (
<View>
...
</View>
)
}
}
The if condition is where the error generates. Why is it happening? It's not even in the return section. Thanks in advance.
There are several issues in the code
filteredPaymentList which is a const is declared twice the second line is not required at all.
You have put ... inside the view, which is considered as a string and requires a Text to wrap and causes the above error. Better change it to actual code and it will work normally.

How to get a reference to the created DOM from a templateResult (not using custom elements)

For those crazy folks like me that wouldn't want for various reasons to use custom elements, is there a way to access the DOM related to a templateResult?
I tried to modify the templateResult's content before rendering but without success... I also looked into templateFactory, but it seems it's desinged for the ultimate (parent) templateResult rendered to a container, not nested templateResults.
const componentA = {
id: 'comp-a',
template(){ return html`<div>No ID yet</div>` }
};
const app = {
template(){
const tmpl = html`<main><div>${ componentA.template() }</div></main>`
// here: use componentA.id to set top element's id
// seems it's too late to change the template, DOM is already created?
// so how to get a reference to the created DOM from a templateResult?
return tmpl
}
};
render( app.template(), document.body);
For example, how could I automatically set an id on the top element of componentA from its id?
The thing is lit-html actually creates TemplateResults which are just representations of the HTML that will be created once render() is called.
In this sense the <div> inside A's template has no particular "meaning" with respect to the TemplateResult representing it, but its instances can still be normally querySelected from the render container.
const tmpl = html`
<main>
<div>
${componentA.template()} <!-- This returns a TemplateResult -->
</div>
</main>
`;
You're still totally allowed to assign an id to the <div>:
const componentA = {
// ...
template() {
return html`
<div id="comp-a"></div>
`;
}
}
If you want to assign the id only at a later stage, you can pass it as argument to the function that creates A's template:
const componentA = {
// ...
template(id) {
return html`
<div id=${id}></div>
`;
}
}

Using React / JSX for Non-JavaScript Code Generation

I was wondering if you could use React/JSX in a code generation framework.
Is there a way to do something like the code below in JSX?
var className = "Person"
return (
//// public class {className}
//// {
////
//// }
);
Where the //// would be some special character or character sequence that signals to JSX parser that this should just be plain text?
Or is there a better approach using React that already exists?
If you're doing this in the browser you can do something like this and then grab the textContent of the <code> element that was rendered when it mounts. I haven't used React on the server but I'm guessing you could use ReactDOMSever's renderToString and then create a simple script that strips the opening and closing tags from your string and you have your code in a text string that you could save to anytype of file using node.
var data = {
class_name : 'User',
method1Name: 'doSomething'
}
class MakeClass extends React.Component {
componentDidMount(){
console.log(this.codeElem.textContent)
}
render() {
let {json} = this.props;
return (
<code ref={c=>this.codeElem=c}>{`
class ${json.class_name} {
constructor() {
// do something
}
${json.method1Name}() {
// this method does something
}
}
`}</code>
)
}
}
ReactDOM.render(
React.createElement(MakeClass, {json: data}),
document.getElementById('root')
);
You can see the full thing here:
http://jsbin.com/rizaqifasi/edit?html,js,console,output

Categories