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'
};