How to use react inside a polymer component? - reactjs

It seems it could posible to use react inside a polymer web component but I couldn’t find a working example, only this, but it seems outdated.
HTML
<link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html" />
<polymer-element name="my-polymer" constructor="" attributes="name">
<template>
<P>I AM {{name}}</P>
<div id="reactContainer"></div>
</template>
<script type="text/jsx">
/** #jsx React.DOM **/
Polymer('my-polymer', {
created: function(){},
ready: function(){},
attached: function(){},
domReady: function(){
React.renderComponent(<MyReact name="REACT INSIDE POLYMER"/>, this.$.reactContainer);
},
detached: function(){},
attributeChanged: function(attrName, oldVal, newVal) {}
});
</script>
</polymer-element>
<my-polymer name="POLYMER"></my-polymer>
JS
/** #jsx React.DOM */
var MyReact = React.createClass({
render: function() {
return (
<p>I AM {this.props.name}</p>
);
}
});

The main things you gotta take care of before, is:
transform the index.jsx into index.js javacript form (https://github.com/jsx/JSX)
babel --plugins transform-react-jsx
Bundle up your reactApp with Traceur Compiler, Babel, Rollup or webPack. Since imports aren't yet implemented in browsers.
make sure you main file index.js, doesn't render's react. That's going to be Polymer's responsibility.
npm run build (obtained with npm run build for reac-redux)
index.js
import React from 'react'
import { render } from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import App from './components/App'
import reducer from './reducers'
window.Render = render;
window.React = React;
window.CreateStore = createStore;
window.Provider = Provider;
window.App = App;
window.Reducer = reducer;
example-component.html
<link rel="import" href="../polymer/polymer-element.html">
<dom-module id="example-component">
<template>
</template>
<script src="./main.bundleFromReact.js"></script>
<script>
class ExampleComponent extends Polymer.Element {
static get is() { return 'example-component'; }
ready() {
super.ready();
const store = CreateStore(Reducer);
Render(
React.createElement(
Provider,
{store: store},
React.createElement(
App,
null
)
),
this.shadowRoot
);
}
}
window.customElements.define(ExampleComponent.is, ExampleComponent);
</script>
</dom-module>
tl;dr
You can see my simplest example without importing here:
<link rel="import" href="../polymer/polymer-element.html">
<script src="../react/react.min.js"></script>
<script src="../react/react-dom.min.js"></script>
<dom-module id="example-component">
<template></template>
<script>
class HelloMessage extends React.Component {
render() {
return React.createElement(
'div',
{}, `Hello ${this.props.name}`);
}
}
class ExampleComponent extends Polymer.Element {
static get is() { return 'example-component'; }
ready() {
super.ready();
var mountPoint = document.createElement('span');
this.shadowRoot.appendChild(mountPoint);
ReactDOM.render(
React.createElement(HelloMessage, {name: 'Maestro'}),
mountPoint
);
}
}
window.customElements.define(ExamplComponent.is, ExamplComponent);
</script>

Related

How do I import react-modal into existing application?

I've been slowly trying to migrate some pieces of an existing, large php/jquery project to use ReactJS, especially using some reusable components. ReactJS has been working well for me, but today I tried to import a library using npm, which is completely new to me.
After running npm install react-modal I see that node_modules\react-modal (along with several other folders) were created. So far, so good.
However, I cannot seem to include that component into my project. If I try import ReactModal from 'react-modal'; at the top of my component's .js file, I get: Uncaught ReferenceError: require is not defined. I get errors thrown if I try to include the node_modules\react-modal\lib\components\Modal.js file directly, which I realize is probably the wrong approach but I'm grasping at straws here. I suspect I'm missing something basic, but I just can't seem to figure this one out. Does anyone have any ideas?
Edit: here is how I include React into my project currently:
<!-- Load React. -->
{if $env=="prod"}
<script src="https://unpkg.com/react#16/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.production.min.js" crossorigin></script>
{* tabs support *}
<script src="https://unpkg.com/prop-types/prop-types.js"></script>
<script src="https://unpkg.com/react-tabs#3/dist/react-tabs.production.min.js"></script>
<link href="https://unpkg.com/react-tabs#3/style/react-tabs.css" rel="stylesheet">
{else}
<script src="https://unpkg.com/react#16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js" crossorigin></script>
{* tabs support *}
<script src="https://unpkg.com/prop-types/prop-types.js"></script>
<script src="https://unpkg.com/react-tabs#3/dist/react-tabs.development.js"></script>
<link href="https://unpkg.com/react-tabs#3/style/react-tabs.css" rel="stylesheet">
{/if}
{* Babel support *}
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
This is the full component (contents of the matchSelector.js file):
import Modal from 'react-modal';
/**
* Select a match with hooks to return the proper match info to the instantiator
*/
class MatchSelector extends React.Component {
/**
* Class Constructor
*
* props expected:
* className - (optional) use if you want to style the picker button/icon differently. Note that
* if given, all standard classes will be overrided.
*
* type - (optional) can be "text", "icon", "both". Default is "both".
*
* text - (optional) if type is "text" or "both", the text to use on the button. Default is "Select Match"
*
*/
constructor(props) {
super(props); // let Dad know what's up
this.state = {showDialog:false}
this.handleClick = this.handleClick.bind(this);
this.handleClose = this.handleClose.bind(this);
}
handleClick(event) {
event.preventDefault();
this.setState({showDialog:true});
}
handleClose() {
this.setState({showDialog:false});
}
render() {
const defaultClassName = "ui-state-default ui-corner-all ui-button compressed";
let className = (odcmp.empty(this.props.className)?defaultClassName:this.props.className);
return (
<React.Fragment>
<button
className={className}
onClick={this.handleClick}>
{this.buttonContent()}
</button>
<MatchSearchDialog
show={this.state.showDialog} />
</React.Fragment>
);
}
buttonContent() {
var text = (odcmp.empty(this.props.text)?"Select Match":this.props.text);
if (odcmp.empty(this.props.type) || (this.props.type.toLowerCase()=="both")) {
return (
<span><span className="ui-icon ui-icon-search inline"></span>{text}</span>
);
} else if (this.props.type.toLowerCase()=="icon") {
return (
<span className="ui-icon ui-icon-search inline"></span>
);
} else {
return text;
}
}
}
class MatchSearchDialog extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<ReactModal isOpen={false}><div>hi</div></ReactModal>
);
}
}
The doc of the npm package state that to import your modal, you need to write:
import Modal from 'react-modal';
It's not import ReactModal from 'react-modal'; as you tried (ReactModal => Modal).
With this eveything works fine for me as you can see on this repro on Stackblitz. Here is the code :
import React, { Component } from "react";
import { render } from "react-dom";
import Hello from "./Hello";
import Modal from 'react-modal';
import "./style.css";
Modal.setAppElement('#root');
const App = () => {
const [modalIsOpen,setIsOpen] = React.useState(false);
const openModal = () => {
setIsOpen(true);
}
const closeModal = () => {
setIsOpen(false);
}
return (
<div>
<p>Start editing to see some magic happen :)</p>
<button onClick={openModal}>Open Modal</button>
<Modal
isOpen={modalIsOpen}
contentLabel="Example Modal"
>
<div>Wow nice modal !</div>
<button onClick={closeModal}>close</button>
</Modal>
</div>
);
};
render(<App />, document.getElementById("root"));
In case anyone runs into this, I wanted to add my resolution.
I was trying to run a bare bones REACTJS project without webpack. react-modal depends on webpack (as does, I'm sure, many React components). As I'm trying to stay light and agile, I removed the react-modal module and "rolled my own" modal dialog.
FYI, the clue is the "require not defined" error in the console - indicating a non-browser (node.js) function was hit. It was expecting to compile (webpack) into a separate js file using the node.js terminology.

Botframework with Reactjs is not working on IE11

botframework with react is not working in IE,
I'm using my index html file similar to
https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/03.a.host-with-react, its working in chrome but not in IE, i tried using webchat-es5.js also.
I'm using token given by bot team.
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Integrate with React</title>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<script src="https://unpkg.com/react#16.5.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16.5.0/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-redux#5.0.7/dist/react-redux.min.js"></script>
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat-es5.js"></script>
<style>
html, body { height: 100% }
body { margin: 0 }
#webchat {
height: 100%;
width: 100%;
}
</style>
</head>
<div id="webchat" role="main"></div>
<script type="text/babel">
function start() {
const { createStore, ReactWebChat } = window.WebChat;
const { Provider } = window.ReactRedux;
const store = createStore();
window.ReactDOM.render(
<Provider store={ store }>
<ReactWebChat
directLine={ window.WebChat.createDirectLine({ token:'mytoken' }) }
storeKey="webchat"
/>
</Provider>,
document.getElementById('webchat')
);
document.querySelector('#webchat > *').focus();
}
start();
</script>
</body>
</html>
working in Chrome but not in IE, somebody help me on this please.
Unfortunatley, the "webchat-es5.js" package was designed for instantiating web chat via the window.WebChat.renderWebChat method. While the "webchat.js" package does allow for using window.ReactDOM.render, it is not designed for older browsers, such as IE.
I played with this a bunch and was simply unable to render web chat using window.ReactDOM.render while also in IE, despite utilizing any number of polyfills. That being said, I was able to get the hosted React web chat sample to work in a proper React project with a few of modifications. Please note, this also makes use of webpack.
Hope of help!
index.js: Nothing special or unexpected here.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './app';
import './css/index.css';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();
app.js: Just some necessary routing.
import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import WebChatView from './webChatView';
class App extends Component {
render() {
return (
<Router>
<div className="App">
<Route path="/" exact component={WebChatView} />
</div>
</Router>
);
}
}
export default App;
webChatView.js: Renders the web chat page (with some necessary styling)
import React, { Component } from 'react';
import WebChatView from './webchatView';
const FragmentStyling = {
'container': {
'display': 'flex',
'justifyContent': 'center'
},
'div': {
'height': '40rem',
'minHeight': '20rem',
'width': '1200px',
'display': 'flex',
'justifyContent': 'space-around',
'marginTop': '2rem'
}
}
class WebChatView extends Component {
render() {
return (
<div style={FragmentStyling.container}>
<div style={FragmentStyling.div}>
<WebChatView id="webchat" role="main" />
</div >
</div>
)
}
}
export default WebChatView;
webchat.js: Several things to note:
Either import '#babel/polyfill' needs to be included or all the 'core-js' imports listed below. Babel recommends importing only the required polyfills (to keep package size down). Those shown below are what is needed. However, using the '#babel' option works, as well.
Simply using fetch as-is breaks due to compatibility issues. There may be other options, but the below 'whatwg-fetch' option works in both IE and Chrome. Others I tested did not.
'fetching' the token needs to be promise-based. Using async/await breaks React web chat in IE.
import 'core-js/es6/map';
import 'core-js/es6/promise'
import 'core-js/es6/set';
import 'core-js/es6/symbol';
import 'core-js/fn/array/find-index';
import 'core-js/fn/array/includes';
import 'core-js/fn/math/sign';
import 'core-js/fn/object/assign';
import 'core-js/fn/string/starts-with';
import { fetch as fetchPolyfill } from 'whatwg-fetch';
import React from 'react';
import ReactWebChat, { createDirectLine } from 'botframework-webchat';
export default class WebChat extends React.Component {
constructor(props) {
super(props);
this.state = {
directLine: null
};
}
componentDidMount() {
this.fetchToken();
}
fetchToken(token) {
fetchPolyfill('http://localhost:3500/directline/token', { method: 'POST' })
.then(res => res.json()) // expecting a json response
.then(json =>
this.setState(() => ({
directLine: createDirectLine(
{
token: json.token
}
)
}))
)
}
render() {
return (
this.state.directLine ?
<ReactWebChat
directLine={this.state.directLine}
/>
:
<div>Connecting to bot…</div>
)
}
}
index.html: The 'react-polyfill.min.js' package needs to be included and should precede any other scripts that might live here.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="//pitzcarraldo.github.io/react-polyfill/react-polyfill.min.js" charSet="UTF-8"></script>
<title>React Web App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
webpack.config.js: The import 'script!react-polyfill' needs to be included at the top of this file.
import 'script!react-polyfill';
const path = require('path');
module.exports = {
entry: ['./src/index.js'],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
},
mode: 'development'
};

React - Coding Error

I am following tutorial from: https://www.youtube.com/watch?v=OzqR10jG1pg
Using Code Editor: https://stackblitz.com
Coding error reads:
Error in index.js (36:10)
'}' expected.
Error line reads:
render: function () {
How do I get this code to work?
Here is my Code:
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
class App extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
render() {
return (
<div>
<Hello name={this.state.name} />
<p>
Start editing to see some magic happen :)
</p>
</div>
);
}
}
render(<App />, document.getElementById('root'));
<div id="example"></div>
<script type="text/babel">
var Bacon = React.createClass({
render: function () {
return (<h3>This is a simple component!</h3>);
}
});
ReactDOM.render(<Bacon />, document.getElementById('example'));
</script>
It looks like you are putting HTML code into your javascript (index.js) file. You should have a separate HTML file for that.
I can see you are trying to render two different apps.
First, when you use ReactDOM.render(<Bacon />, document.getElementById('example')); you're telling React to render the component Bacon in the HTML element that has an ID attribute 'example'.
Then, with render(<App />, document.getElementById('root'));, React will look for an element that has an ID attribute 'root'.
So you should have both elements in your HTML file, like the snippet below.
// index.js
class App extends React.Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
render() {
return (
<div>
<div>{this.state.name}</div>
<p>
Start editing to see some magic happen :)
</p>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<!-- index.html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="example"></div>
<div id="root"></div>
<script type="text/babel">
var Bacon = React.createClass({
render: function () {
return (<h3>This is a simple component!</h3>);
}
});
ReactDOM.render(<Bacon />, document.getElementById('example'));
</script>

adding jquery plugin is not working in react app; TypeError: this.$el.chosen is not a function

I am learning React and following integrating other Libraries chapter and tried the same they have suggested but getting below error
TypeError: this.$el.chosen is not a function
Chosen.componentDidMount
src/App.js:18
componentDidMount() {
this.$el = $(this.el);
> this.$el.chosen();
}
react website provides example codepen where they have added the jquery and chosen plugin js in dependencies and I have added jquery and chosen library js file in index.html and also added jquery using npm install jquery --save so that it can be imported in App.js
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.6.2/chosen.jquery.min.js"></script>
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
</body>
</html>
App.js
import React, { Component } from 'react';
import $ from 'jquery';
class Chosen extends Component {
componentDidMount() {
this.$el = $(this.el);
this.$el.chosen();
}
componentWillUnmount() {
this.$el.chosen('destroy');
}
render() {
return (
<div >
<select className="Chosen-select" ref={el => this.el = el}>
{this.props.children}
</select>
</div>
);
}
}
function Example() {
return (
<Chosen >
<option >vanila</option>
<option >strawberry</option>
<option >chocolate</option>
</Chosen>
);
}
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<section>
<Example/>
</section>
</div>
);
}
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
Why I am getting this error and how to fix it?
Got it to work by following these steps (after creating a project using create-react-app)
npm install jquery --save
npm install chosen-js --save
Add this in line #1 of node_modules/chosen-js/chosen.jquery.js
import jQuery from 'jquery'
As per this answer
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import $ from 'jquery'
import "chosen-js/chosen.css";
import "chosen-js/chosen.jquery.js";
class Chosen extends React.Component {
componentDidMount() {
this.$el = $(this.el);
this.$el.chosen();
this.handleChange = this.handleChange.bind(this);
this.$el.on('change', this.handleChange);
}
componentDidUnmount() {
this.$el.off('change', this.handleChange);
this.$el.chosen('destroy');
}
handleChange(e) {
this.props.onChange(e.target.value);
}
render() {
return (
<div>
<select className="Chosen-select" style={{width: "200px"}} ref={el => this.el = el}>
{this.props.children}
</select>
</div>
);
}
}
function Example() {
return (
<Chosen className="chosen-container chosen-container-single" onChange={value => console.log(value)}>
<option>vanilla</option>
<option>chocolate</option>
<option>strawberry</option>
</Chosen>
);
}
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
<Example/>
</p>
</div>
);
}
}
export default App;
I have also face the same issue while reading the documentation. But instead of updating the "node_modules/chosen-js/chosen.jquery.js" file, I prefer to Use the ProvidePlugin to inject implicit globals in webpack.config.js
But when we create an application using create-react-app we didn't find the webpack.config.js file.
You will need to eject the react application. But you should first read from the following links before ejecting the application(If you’re a power user and you aren’t happy with the default configuration).
Links:-
https://github.com/satendra02/react-chrome-extension/wiki/What-happens-when-you-eject-Create-React-App
https://medium.com/curated-by-versett/dont-eject-your-create-react-app-b123c5247741
You will need to run the following command to eject the react application as this command will remove the single build dependency from your project and also copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc.) into your project as dependencies in package.json
npm run eject
Install the dependencies
npm install jquery chosen-js --save
Now edit your webpack.config.js file and update the config object as follow
return {
...
module: {
...
},
plugins: [
...
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
]
...
}
Chosen.js
import React from 'react';
import $ from "jquery";
import "chosen-js/chosen.css";
import "chosen-js/chosen.jquery.js";
class Chosen extends React.Component {
componentDidMount() {
this.$el = $(this.el);
this.$el.chosen();
this.handleChange = this.handleChange.bind(this);
this.$el.on("change", this.handleChange);
}
componentDidUpdate(prevProps) {
if (prevProps.children !== this.props.children) {
this.$el.trigger("chosen:updated");
}
}
componentWillUnmount() {
this.$el.off("change", this.handleChange);
this.$el.chosen("destroy");
}
handleChange(e) {
this.props.onChange(e.target.value);
}
render() {
return (
<div>
<select className="Chosen-select" ref={(el) => (this.el = el)}>
{this.props.children}
</select>
</div>
);
}
}
It seems like a issue related with dependency.
I notice that you include JQuery and its chosen plugin with CDN which means it is declared globally. But in third line of App.js you import $ from 'jquery'; which may introduce JQuery locally. In my experience, React will refer $ to local JQuery which is not with the plugin.
I suggest that you could try comment out import $ from 'jquery' and try again.
Good luck!
Use
window.$("#infomodal").modal("hide");

integrating js code inside react component

I have converted a component that displays chart bar, and it requires this js snippet to run, what is the correct way of integrating it inside my JSX code?
<script>
/** START JS Init "Peity" Bar (Sidebars/With Avatar & Stats) from sidebar-avatar-stats.html **/
$(".bar.peity-bar-primary-avatar-stats").peity("bar", {
fill: ["#2D99DC"],
width: 130,
})
</script>
I have seen this libraries on npm website, but they mostly deal with external scripts not internal
here is my component:
import React, { Component } from 'react';
export default class App extends Component {
render() {
return (
<div>
"How can I render js code here?"
</div>
);
}
}
You can use refs and componentDidMount callback in order to initialize jquery plugins, like so
class App extends React.Component {
componentDidMount() {
$(this.barChart).peity("bar", {
fill: ["#2D99DC"], width: 130
});
}
render() {
return <div>
<div ref={ (node) => { this.barChart = node } }>
<span class="bar">5,3,9,6,5,9,7,3,5,2</span>
<span class="bar">5,3,2,-1,-3,-2,2,3,5,2</span>
<span class="bar">0,-3,-6,-4,-5,-4,-7,-3,-5,-2</span>
</div>
</div>;
}
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/peity/3.2.1/jquery.peity.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>
You should use componentDidMount lifecycle hook.
Add this to your component code:
componentDidMount() {
$(".bar.peity-bar-primary-avatar-stats").peity("bar", {
fill: ["#2D99DC"],
width: 130,
})
}

Resources