J'utilise cette bibliothèque: html-to-react
car j'ai trouvé qu'il était possible de "compiler" du HTML en tant que chaîne pour React Composants.
Nous faisons un système basé sur des widgets et ils peuvent changer au fil du temps (c'est-à-dire ajouter/supprimer/mettre à jour/etc), nous prévoyons donc d'envoyer le widget HTML de la base de données vers l'avant, ce qui se fait à l'aide de React.
J'ai réussi à créer un widget simple en utilisant HTML, maintenant j'essaie ce widget pour répondre aux événements de clic, alors j'ai pensé à ajouter la méthode onclick=method()
à partir du HTML ou onClick={method}
À partir de React. Cependant, je n'ai pas pu obtenir la sortie souhaitée car je reçois ces erreurs dans la console de mon navigateur.
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)
Le code que j'utilise est le suivant:
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"
}
}
Est-il possible d'obtenir un alert
ou quelque chose de similaire en utilisant la bibliothèque ci-dessus pour analyser HTML vers React Composants? Si oui, comment pourrais-je le faire? Ou qu'est-ce que je fais mal ?
Il n'est pas nécessaire que ce soit spécifiquement la bibliothèque que j'utilise, s'il y en a une autre avec laquelle vous avez travaillé et fait quelque chose de similaire, je suis ouvert à recevoir ces recommandations (Remarque, je ne demande pas de logiciel ou de bibliothèque , mais comment appeler la méthode onClick
dans la chaîne contenant mon code HTML ou une solution de contournement)
Après avoir essayé quelque chose, j'ai trouvé que supprimer cette ligne:
var reactHtml = ReactDOMServer.renderToStaticMarkup(reactElement);
Supprime l'un des messages. La bibliothèque utilise cet élément pour tester si le HTML actuel et celui analysé sont identiques. Je n'en avais pas besoin pour mon cas mais cela laisse toujours l'erreur actuelle dans la 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)
Après quelques recherches, j'ai trouvé dangerousSetInnerHTML
dans cette réponse
J'ai ensuite essayé de suivre cette réponse en plaçant un alert
dans mon HTML comme suit:
'<label htmlFor="float-input" onclick="alert(\'Hello\')">Hello2</label>'
Et cela a déclenché le alert
, cependant si j'ai déclaré myFunction
comme dans le code ci-dessous (remarquez que j'ai essayé de le déclarer comme function
en dehors de la classe, à l'intérieur et aussi comme var myFunction = function() { ... }
tous ensemble et séparés):
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;
Mais cette fois, j'obtiens une nouvelle erreur:
ReferenceError: myFunction is not defined[Learn More]
J'ai trouvé une question similaire: Gestion onClick d'une balise <a> à l'intérieur de dangerouslySetInnerHTML/regular html avec ce problème, et j'ai essayé d'enquêter un peu plus et j'ai trouvé ce commentaire qui indique que les événements de dangerouslySetInnerHTML
ne seront pas déclenchés de cette façon et établit un lien vers docs .
Donc, même si cela semblait être une solution de contournement lorsque j'ai obtenu un alert
lorsqu'il a été écrit directement à partir de la méthode onclick
, ou probablement je ne l'ai pas fait de la bonne manière, donc si quelqu'un avec plus l'expérience pourrait l'essayer et clarifier, serait formidable.
J'ai trouvé un moyen d'afficher un alert
de cette manière:
dangerouslySetInnerHTML
componentDidMound()
de React utilisez du Javascript pur pour y ajouter la fonction onclick
.Cependant, ce que nous essayons de faire est :
addTwoNumbers
ou quelque chose comme çaonclick
ou onClick
depuis la chaîne HTML appelant la fonction addTwoNumbers
.addTwoNumbers
et juste pour écrire le code HTML pour celui-ci, l'enregistrer sur la base de données et le récupérer et ensuite l'utiliser.Quelque chose comme:
...
<label onClick={myFunction}> My Label </label>
...
Ou comme je l'ai dit plus haut:
...
<label onClick={addTwoNumbers}> My Label </label>
...
Le code qui me permet d'obtenir un alert
est le suivant:
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;
Dans cet esprit, connaissez-vous une autre façon de faire ce que j'essaie de faire?
La solution est un peu hacky, copiez-collez dans codesandbox
class App extends Component {
constructor(props) {
super(props);
this.myfunc = this.myfunc.bind(this);
}
componentDidMount() {
window.myfunc = this.myfunc;
}
myfunc() {
console.log("from myfunc");
}
componentWillUnmount() {
window.myfunc = null;
}
render() {
let inputhtml = "<a onclick=window.myfunc()>HelloWorld</a>";
return (
<div style={styles}>
<div dangerouslySetInnerHTML={{ __html: inputhtml }} />
</div>
);
}
}
Je ne sais pas si cela fonctionnerait pour votre cas particulier, mais une idée est de ne pas analyser HTML du tout. Vous pouvez demander à webpack de générer des ensembles séparés pour différents ensembles de fichiers. Maintenant, je ne l'ai jamais fait, mais j'ai lu plusieurs fois ce que vous pouvez; par exemple, this .
Ensuite, vous pouvez avoir un main.bundle.js qui contient toutes les parties de votre site qui ne changent pas. Créez également un widget1.bundle.js et ainsi de suite pour chaque widget qui peut changer. Importez tous ceux sur votre index.html. Ensuite, configurez votre serveur Web pour ne jamais mettre en cache les petits bundles (widget1, etc.). Chaque fois que l'utilisateur accède au site Web, il télécharge à nouveau ces widgets, les mettant à jour efficacement. Si vous voulez être plus sophistiqué, vous pouvez fournir une API avec la version actuelle de chaque widget, et mettre un champ supplémentaire sur le bundle de widgets avec la version, afin que vous puissiez vérifier périodiquement si les composants sont à jour, dans le événement que l'utilisateur n'a pas rechargé la page depuis un certain temps. Si vous découvrez un composant obsolète, forcez simplement le rechargement et le navigateur s'assurera de récupérer la dernière version.
Je sais que c'est un chemin totalement différent de celui que vous utilisez, mais si c'est bon pour votre cas particulier, je pense qu'il sera plus simple, plus facile à mettre en œuvre et garantira la stabilité, plus maintenable et globalement une meilleure solution que l'analyse manuelle du html et gérer vous-même toutes les demandes.