vnext Widgets: Bootstrapping

by Troy Rhinehart

why
how

why

  • ReactDOMServer

  • Dynamic Content

  • Minimal Client JS

why

ReactDOMServeR

  class App extends React.Component {
    handleClick = (e) => {
      console.log(e);
    };
    render() {
      return (
        <h1 onClick={ this.handleClick }>
          Hello World
        </h1>
      );
    }
  }


  <h1
    data-reactroot=""
    data-reactid="1"
    data-react-checksum="55251490"
  >
    Hello World
  </h1>
                         ReactDOMServer.renderToString(<App/>);

why

DYNAMIC CONTENT

  • interactions
  • external resources
  • state validation

why

Minimal Client Resources

  • no stores
  • no context
  • return null

how

  • props/context

  • webpack RAW-LOADER

  • Return null

HOW

PROPS/CONTEXT

  import React from 'react';
  import PropTypes from 'prop-types';
  import { components } from '@wsb/guac-widget-core';
  import Component from './Component';
  import rawComponent from 'webpack-raw!./raw';

  const { Bootstrap } = components;

  export default function Bootstrapped(props) {
    return (
      <Bootstrap
        {...props}
        Component={ Component }
        rawComponentScript={ rawComponent }
        exportedComponent={ 'Bootstrapped' }
      />
    );
  }
  BootstrappedComponent.propTypes = {
    renderMode: PropTypes.string.isRequired
  };
  <Script children={ [
    rawComponentScript,
    `(function() {
      var props = ${JSON.stringify(widgetProps)};
      var context = ${JSON.stringify(contextProps)};
      if (context.theme) {
        context.theme = window.wsb[context.theme];
      }
      ReactDOM.render(
        React.createElement(
          Core.UX2.Base,
          context,
          React.createElement(
            window.wsb['${exportedComponent}'],
            props
          )
        ),
        document.getElementById('${domTargetId}')
      );
    })();`
  ] }/>

HOW

WEBPACK RAW-LOADER

  • externals
    • React/ReactDOM
    • Lodash
    • Immutable
  • minified/uglified
  • commonjs
  • webpack-null-loader

HOW

RETURN NULL - before

  <div>
    <ScrollToButton
      target="#target"
      children="Click Me - Button"
    />
    <ScrollToLink
      target="#target"
      children="Click Me - Link"
    />
    <ScrollToImage
      target="#target"
      src="//img.com"
    />
    <ScrollToBackground
      target="#target"
      backgroundImage="//img.com"
    />
    ...
    <div id="target">...</div>
  </div>

HOW

RETURN NULL - AFTER

  <div>
    <ScrollTo target="#target">
      <UX2.Element.Button>Click Me - Button</UX2.Element.Button>
    </ScrollTo>
    <ScrollTo target="#target">
      <UX2.Element.Link>Click Me - Link</UX2.Element.Link>
    </ScrollTo>
    <ScrollTo target="#target">
      <UX2.Element.Image src="//img.com"/>
    </ScrollTo>
    <ScrollTo target="#target">
      <UX2.Element.Background
        backgroundImage="//img.com"
      />
    </ScrollTo>
    ...
    <div id="target">...</div>
  </div>

HOW

RETURN NULL - BOOTSTRAP

 

  class ScrollTo extends React.Component {
    constructor() {
      super(...arguments);
      this.id = _.uniqueId('scroll-to');
    }
    render() {
      const { target, children, ...props } = this.props;
      return (
        <UX2.Element { ...props } id={ this.id }>
          { React.Children.only(children) }
          <Bootstrap
            target={ target }
            subject={ `${this.id} > :first-child` }
            Component={ ScrollToComponent }
            rawComponentScript={ rawComponent }
            exportedComponent={ 'ScrollTo' }
          />
        </UX2.Element>
      );
    }
  }

HOW

RETURN NULL - Component

  class ScrollToComponent extends React.Component {
    handleClick = (e) => {
      // scrollTo logic using this.props.target
    };
    componentDidMount() {
      this.subject = document.querySelector(this.props.subject);
      this.subject && this.subject.addEventListener('click', this.handleClick);
    }
    componentWillUnmount() {
      this.subject && this.subject.removeEventListener('click', this.handleClick);
    }
    render() {
      return null;
    }
  }

Questions?

Made with Slides.com