I'm using this library: html-to-react
as I found that it was possible to "compile" HTML as a String to React Components.
We're doing a system based on widgets and they might change over time (i.e. add / remove / update / etc), so we're planning to send the widget HTML from the database to the front which is done using React.
I've successfully done a simple widget using HTML, now I'm trying this widget to respond to click events, so I thought on adding onclick=method()
method from HTML or onClick={method}
from React. However I've not been able to get the desired output as I'm getting these errors in my browser's console.
Warning: Invalid event handler property `onclick`. React events use the camelCase naming convention, for example `onClick`.
in label
in span
in div
Warning: Invalid event handler property `onclick`. Did you mean `onClick`?
in label
in span
in div
in DireccionComponent (at App.js:51)
in div (at App.js:50)
in GridItem (created by ReactGridLayout)
in div (created by ReactGridLayout)
in ReactGridLayout (at App.js:49)
in App (at index.js:11)
The code I'm using is the following:
App.js
import React, { Component } from 'react';
import './App.css';
import DireccionComponent from './DireccionComponent.js';
class App extends Component {
render() {
return (
<DireccionComponent />
);
}
}
export default App;
DireccionComponent.js
import React, {Component} from 'react';
var ReactDOMServer = require('react-dom/server');
var HtmlToReactParser = require('html-to-react').Parser;
let htmlInput = ''
+ '<div>'
+ '<center><label className="title">Widget</label></center>'
+ '<span className="ui-float-label">'
+ '<label htmlFor="float-input" onClick={this.myFunction}>Hello</label>'
+ '</span>'
+ '</div>';
var htmlToReactParser = new HtmlToReactParser();
var reactElement = htmlToReactParser.parse(htmlInput);
var reactHtml = ReactDOMServer.renderToStaticMarkup(reactElement);
class DireccionComponent extends Component {
constructor(props) {
super (props);
this.myFunction = this.myFunction.bind(this);
}
render() {
return (
reactElement
)
}
myFunction() {
console.log('Hola');
alert("Hola");
}
}
export default DireccionComponent;
package.json
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"html-to-react": "^1.3.3",
"primereact": "^1.5.1",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-dom-server": "0.0.5",
"react-grid-layout": "^0.16.6",
"react-scripts": "1.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
Is it possible to get an alert
or something similar using the above library to parse HTML to React Components? If so, how could I do it? Or what am I doing wrong?
Edit
It doesn't have to be specifically the library I'm using, if there's another one you've worked with and done something similar, I'm open to receive this recommendations (Note, I'm not asking for a software or library, but how to call the onClick
method inside the String containing my HTML or a workaround)
Edit 2
After trying something I found that removing this line:
var reactHtml = ReactDOMServer.renderToStaticMarkup(reactElement);
Gets rid of one of the messages. The library uses that element to test if both the current HTML and the parsed one are the same. I didn't needed it for my case but that still leaves the current error in the console:
Warning: Invalid event handler property `onclick`. Did you mean `onClick`?
in label
in span
in div
in DireccionComponent (at App.js:47)
in App (at index.js:11)
Edit 3
After some investigation I found dangerousSetInnerHTML
in this answer
Then I tried to follow this answer an placing an alert
inside my HTML as follows:
'<label htmlFor="float-input" onclick="alert(\'Hello\')">Hello2</label>'
And it triggered the alert
, however if I declared myFunction
like in the code below (notice I tried to declare it as a function
outside the class, inside it and also as var myFunction = function() { ... }
all together and separated):
import React, {Component} from 'react';
var ReactDOMServer = require('react-dom/server');
var HtmlToReactParser = require('html-to-react').Parser;
let htmlInput = ''
//+ '<div>'
+ '<center><label className="title">Widget</label></center>'
+ '<span className="ui-float-label">'
+ '<label htmlFor="float-input" onclick="myFunction()">Hello2</label>'
+ '</span>'
//+ '</div>';
var htmlToReactParser = new HtmlToReactParser();
var reactElement = htmlToReactParser.parse(htmlInput);
class DireccionComponent extends Component {
constructor(props) {
super (props);
this.myFunction = this.myFunction.bind(this);
}
render() {
return (
<div dangerouslySetInnerHTML={{__html: htmlInput}}>
</div>
)
}
myFunction() {
console.log('Hola');
alert("Hola");
}
}
function myFunction() {
console.log('Hola');
alert("Hola");
}
export default DireccionComponent;
But this time I get a new error:
ReferenceError: myFunction is not defined[Learn More]
I found a similar question: Handling onClick of a <a> tag inside of dangerouslySetInnerHTML/regular html with this problem, and tried to investigate a little more and found this comment which says that the events from the dangerouslySetInnerHTML
won't be triggered this way and links to the docs.
So, while this seemed to be a workaround when I got an alert
when written directly from the onclick
method, or probably I didn't do it in the correct way, so if someone with more experience could try it and clarify, would be great.
Edit 4
I found a way to show an alert
in this way:
- Write the HTML as a String
- Set the HTML through
dangerouslySetInnerHTML
- On
componentDidMound()
function from React use pure Javascript to addonclick
function to it. - Success
However, what we're trying to do is:
- Create some methods, for example:
addTwoNumbers
or something like that - Send an
onclick
oronClick
from within the HTML String callingaddTwoNumbers
function. - Repeat everytime we need to add a new component that needs to use the
addTwoNumbers
method and just have to write the HTML for it, save it on the database and retrieve it and then just use it.
Something like:
...
<label onClick={myFunction}> My Label </label>
...
Or as I said above:
...
<label onClick={addTwoNumbers}> My Label </label>
...
The code that allows me to get an alert
is the following:
import React, {Component} from 'react';
import Parser from 'html-react-parser';
import {render} from 'react-dom';
var ReactDOMServer = require('react-dom/server');
var HtmlToReactParser = require('html-to-react').Parser;
let htmlInput = ''
//+ '<div>'
+ '<center><label className="title">Widget</label></center>'
+ '<span className="ui-float-label">'
+ '<label htmlFor="float-input" id="myLabel">Hello2</label>'
+ '</span>'
//+ '</div>';
var htmlToReactParser = new HtmlToReactParser();
var reactElement = htmlToReactParser.parse(htmlInput);
class DireccionComponent extends Component {
constructor(props) {
super (props);
this.myFunction = this.myFunction.bind(this);
}
render() {
return (
<div dangerouslySetInnerHTML={{__html: htmlInput}}>
</div>
)
}
componentDidMount() {
console.log('DONE');
let myLabel = document.getElementById("myLabel");
myLabel.onclick = function() {
alert();
console.log('clicked');
}
console.log(myLabel);
}
myFunction() {
console.log('Hola');
alert("Hola");
}
}
function myFunction() {
console.log('Hola');
alert("Hola");
}
export default DireccionComponent;
With this in mind, do you know any other way to do what I'm trying to do?