plone / volto

React-based frontend for the Plone Content Management System
https://demo.plone.org/
MIT License
460 stars 624 forks source link

Adding Client Only - React Component #760

Closed medicareamaze closed 5 years ago

medicareamaze commented 5 years ago

Hi, I am extending the custom View example to add a Microsoft bot react component following this tutorial - https://plone-training.readthedocs.io/en/master/volto/custom-views.html.

This gives an error stating that window is not defined. This is because the microsoft bot chat control cannot be rendered server side and should be rendered on client side only.

How can I force Volto to render this control on client side only and get past this issue?

My Code is as follows:

import React from 'react';
import PropTypes from 'prop-types';
import Helmet from 'react-helmet';
import { Link } from 'react-router-dom';
import { Container, Image } from 'semantic-ui-react';
import { FormattedMessage } from 'react-intl';
import MinimizableWebChat from '../BotWidget/MinimizableWebChat'
//import ReactWebChat, { createDirectLine } from 'botframework-webchat';
/**
 * Full view component class.
 * @function FullView
 * @param {Object} content Content object.
 * @returns {string} Markup of the component.
 */
const FullView = ({ content }) => (
  <Container className="view-wrapper">
    <Helmet title={content.title} />

        <MinimizableWebChat />
    <article id="content">
      <header>
        <h1 className="documentFirstHeading">sam - {content.title}</h1>
        {content.description && (
          <p className="documentDescription">{content.description}</p>
        )}
      </header>
      <section id="content-core">
        {content.items.map(item => (
          <article key={item.url}>
            <h2>
              <Link to={item.url} title={item['@type']}>
                {item.title}
              </Link>
            </h2>
            {item.image && (
              <Image
                clearing
                floated="right"
                alt={item.image_caption ? item.image_caption : item.title}
                src={item.image.scales.thumb.download}
              />
            )}
            {item.description && <p>{item.description}</p>}
            {item.text &&
              item.text.data && (
                <p dangerouslySetInnerHTML={{ __html: item.text.data }} />
              )}
          </article>
        ))}
      </section>
    </article>
  </Container>
);

/**
 * Property types.
 * @property {Object} propTypes Property types.
 * @static
 */
FullView.propTypes = {
  /**
   * Content of the object
   */
  content: PropTypes.shape({
    /**
     * Title of the object
     */
    title: PropTypes.string,
    /**
     * Description of the object
     */
    description: PropTypes.string,
    /**
     * Child items of the object
     */
    items: PropTypes.arrayOf(
      PropTypes.shape({
        /**
         * Title of the item
         */
        title: PropTypes.string,
        /**
         * Description of the item
         */
        description: PropTypes.string,
        /**
         * Url of the item
         */
        url: PropTypes.string,
        /**
         * Image of the item
         */
        image: PropTypes.object,
        /**
         * Image caption of the item
         */
        image_caption: PropTypes.string,
        /**
         * Type of the item
         */
        '@type': PropTypes.string,
      }),
    ),
  }).isRequired,
};

export default FullView;
tisto commented 5 years ago

@medicareamaze please provide the full traceback.

sneridagh commented 5 years ago

@medicareamaze You can restrict code to run only on the client or on the server by using some special globals that is in place:

SERVER and CLIENT

So you can do something like is done here: https://github.com/plone/volto/blob/d2e2453359f03dd1f23f3b3a074ce06a17302db3/src/components/manage/Preferences/PersonalPreferences.jsx#L180

tisto commented 5 years ago

Question answered. Closing. Feel free to re-open if you disagree.

medicareamaze commented 5 years ago

@sneridagh , Sorry for the delayed response. The problem was with import statement - I could not even add an import statement that referenced the Microsoft Bot framework library. I eneded up using require as follows

componentDidMount() {

    this.setState({ WebChat: require('./WebChat').WebChat });
    let obj = require('botframework-webchat')
    this.setState({
    styleSet: obj.createStyleSet({
        backgroundColor: 'Transparent'
      })
    });`
 this.setState({ showChat: true });
}

render() {
  return (
     {
              showChat ?
              <WebChat
                className="react-web-chat"export class  WebChat
                onFetchToken={ this.handleFetchToken }
                store={ store }
                styleSet={ styleSet }
                token={ token }
                user = { user }

              />
              : 
              'Loading Chat'
              }
       )
}