react-html-connector
v0.2.6
Published
A JavaScript function that eases integratation between React (or Preact) into existing server-side templating.
Downloads
30
Maintainers
Readme
🔌 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 [email protected].
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.