react-html-connector

0.2.6 • Public • Published

🔌 React HTML Connector ·

A JavaScript function that eases integration of React (or Preact) components into existing server-side templating.

Works with:

Development

This package is still considered experimental. This means that it works as intended, however features may still change or get removed in future versions. It is currently used in-house by the team at OpenUp, however feel free to try it out and provide feedback via Github issues. If it addresses a use-case that is important to you please let me know at schalk@openup.org.za.

Usage

This package is intended to be imported into a NodeJS module resolver like Webpack.

However it is built in accordance with the UMD JavaScript specification. This means that it can also be pulled directly into the browser via a <script> tag from the following URL:

<script src="http://unpkg.com/react-html-connector"></script>

Getting Started

1. Make sure that you have the latest version of NodeJS installed:
2. Install the package alongside React and React DOM:
npm install --save react react-dom react-html-connector
3. Create your server-side template:
// Users.php


<body>
  <div data-component="Users">
    <h1 data-title>Users List</h1>
    <ul>
      <?php foreach ($user_array as $user): ?>
        <li data-users <?php $user[active] ? echo "data-active" : null ?>
          <span data-name><?php $user[name] ?></span>
        </li>
      <?php endforeach ?>
    </ul>
  </div>
</body>


<script src="scripts.min.js"></script>
4. Create your React component
// Users.jsx


class Users extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      showAll: true,
    }
    
    this.toggleShowAll = this.toggleShowAll.bind(this);
  }

  toggleShowAll() {
    this.setState({ showAll: !this.state.showAll })
  }

  render() {
    return (
      <div>
        <h1>{this.props.title}</h1>
        <ul>
          {
            this.props.users.map((user) => {
              if (!this.state.showAll && !user.active) {
                return null;
              }

              return (
                <li key={user.id}>
                  <span>{user.name}</span>
                </li>
              )
            })
          }
        </ul>
        <button onClick={this.toggleShowAll}>
          {this.state.showAll ? 'Hide inactive' : 'Show inactive'}
        </button>
      </div>
    )
  }
}
4. Connect React component to your 'data-component' attribute:
// scripts.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import ReactHtmlConnector from 'react-html-connector';


// Create an instance of React HTML Connector.
const userConnector = new ReactHtmlConnector(React.createElement, ReactDOM.render);


// Define how values from template should be passed as props.
const query = {
  title: 'innerHTML',
  users: [
    {
      id: 'number',
      active: 'boolean',
      name: 'innerHTML',
    }
  ]
}


// Call `connect` to bind the 'User' component and associated properties to your template.
userConnector.connect(Users, 'Users', query)
5. Congrats! Your component should be bound to the data-component="Users" attribute.

View a live Codepen example of the above at https://codepen.io/schalkventer/pen/oyJeqg.

API

ReactHtmlConnector

The react-html-connector package exposes a JavaScript class. The constructor associated with this class returns an object with various methods that can be called to ease integration of React with server-side templating.

const connectorInstance = new ReactHtmlConnector(createElement, render, options)
createElement <function> required

Needs to be a React (or a React-like) createElement method (for example: React.createElement). By passing this manually you are able to pass a specific version of React or React-like library. In order to use this package with Preact you need to pass Hyperscript instead of the React createElement method (for example: Preact.h).

render <function> required

Needs to be a React (or React-like) render method (for example: ReactDOM.render). By passing this manually you are able to pass a specific version of React DOM or React-like library. In order to use this package with Preact you need to pass the Preact render method instead of the React DOM render method (for example: Preact.render).

options <Object> optional | default: null

Accepts an object of key-value pairs that set specific change the way the returned methods work. See the upcoming parameters for a list of valid options values.

options.scope <HTMLelement>optional | default: window.document.body

Restricts the returned connect and nodeQuery methods' searchable range to a specifc HTML node and its children. Useful for avoid conflicting attribute names used elsewhere in your templates.

options.attribute <string>optional | default: 'data-component'

Changes the name of the attribute used to bind components to your templates. Useful when data-component is already in use or you want to use a more specific attribute like data-react-compoment.

options.library <'react' | 'preact'> optional | default: 'react'

Changes how the returned connect method parses params. For example, in Preact you need to pass a fourth parameter into preact.render to ensure that a component replaces the targeted HTML node, and not simply appends it to the existing content.

options.store <Object> optional | default: null

Description pending...

options.provider <function> optional | default: null

Description pending...

Methods returned from ReactHtmlConnector constructor:

const connectorInstance = new ReactHtmlConnector(createElement, render, options);
connectorInstance.connect(_component_, _query_);
const customQuery = connectorInstance.nodeQuery(_query_);
connectorInstance.connect.component <React Component> required

The React (or React-like) component that will be bound to a specific data-component attribute in your template.

connectorInstance.connect.name <string> required

The string value used in the data-component attribute of the HTML node you want to target. You can have multiple of the same data-component string in a template to initialise multiple instances of a component. Note that the node itself (and everything inside) will be swapped out for the React component.

connectorInstance.connect.query <Object | function> optional | default: {}

Object literal that instructs what (and how) values should be parsed from your template into props and passed to the component. The object passed to this parameter uses a custom schema, loosely inspired by GraphQl. This schema will be documented in more detail at some point (See Issue #2.

Alternatively, a callback function can be passed to this parameter to override the default querying behaviour above. This callback automatically passes the HTML node itself as its first argument. It also passes the nodeQuery method (covered below) as it's second argument. The callback should return an object that will then be passed as props to the React component.

connectorInstance.nodeQuery.query <Object | function> optional | default: {}

Similar to instance.connect.query, however this method allows you to use the custom querying method independantly of the instance.connect method. Useful if you want parse values in your template independantly or before the component is rendered.

Package Sidebar

Install

npm i react-html-connector

Weekly Downloads

6

Version

0.2.6

License

ISC

Unpacked Size

112 kB

Total Files

8

Last publish

Collaborators

  • schalkventer