0.1.0 • Published 6 years ago

@ddlab/renderer v0.1.0

Weekly downloads
1
License
ISC
Repository
gitlab
Last release
6 years ago

@ddlab/renderer

npm i @ddlab/renderer

This lib was written for educational purposes only. Not recommended for production use.

A tool to build user interfaces with javascript (or typescript) in a declarative fashion.

Features:

  • Typescript declarations
  • JSX support
  • uses virtual DOM (no unecessary DOM updates, etc.)
  • component state management (withState())
  • simple hash router (withRoutes())

Usage

Getting Started

The very basic example:

import {h, bootstrap} from '@ddlab/renderer';
const MyComponent = () => h.div([
    h.h1('Welcome'),
    h.p('to the party')
]);

bootstrap(document.body, MyComponent);

The same example in JSX (see JSX setup section):

import {h, bootstrap} from '@ddlab/renderer';
const MyComponent = () => (
    <div>
        <h1>Welcome</h1>
        <p>to the party</p>
    </div>
);

bootstrap(document.body, MyComponent);

Bootstrapping

Bootstrap the RootComponent to an element using bootstrap(element, RootComponent) function. E.g.:

import {h, bootstrap} from '@ddlab/renderer';
const Home = () => h.div('Hello world!');
bootstrap(document.body, Home);

Components

Abstract out your app's UI elements to components and compose out of it. E.g.:

import {h, bootstrap} from '@ddlab/renderer';
const Header = () => h.h1('Welcome');
const Content = () => h.div('This is content.');
const Home = () => h.div([Header(), Content()]);
bootstrap(document.body, Home);

Attributes

The first argument accepts the attributes object, i.e. h.div(attributes, 'content...'). E.g.:

const style = {color: 'white', backgroundColor: 'blue'}; // *
h.div({class: 'content', style}, 'content...');

* camelCase keys in style object will be converted to kebab-case during rendering.

DOM Events

h.div({
    onClick: e => console.log(e),
    onKeypress: e => alert(e.key),
    // ... any other event
}, 'content...')

Hooks

There are few component specific events (hooks):

  • onCreate() - called on component creation
  • onRemove() - called on component removal
  • onUpdate() - called on props/contents update
  • shouldUpdate(newConfig, oldConfig) - when it returns false, it prevents the component from being rerendered E.g.: h.div({onCreate: () => console.log('hello world!')}, 'content...')

Dynamic Content (using props)

const Counter = (props) => h.div(`#${props.count} visits.`);

const Home = () => h.div([
    Counter({count: 99})
]);

State Management (using withState())

const StatefulComponent = withState(Component) - withState is a hoc which wraps a Component in a returned StatefulComponent.

Wrapping a Component with setState(Component) adds state and setState to the Component's props. Calling setState(changes) updates the state object and rerenders the Component. E.g.:

import {h, withState} from '@ddlab/renderer';
const StatefulCounter = () => withState(p => h.div([
    h.div(`#${p.state.count} clicks.`),
    h.button({
        onClick: () => p.setState(p.state.count + 1)
    }, 'Click me')
]));

Router (using withRoutes())

withRoutes() is a hoc which passes different children for different location hashes to a target component. Example of router configuration:

import {h, withRoutes} from '@ddlab/renderer';

const Home = () => h.div('Home page');
const About = () => h.div('About page');

const RootComponent = withRoutes(h.div, {
    'home': Home,
    'about': About
});

Now setting hash in address bar to '#home' loads Home component & About component for '#about'.

Force rerender

Examine withState & withRoutes source to see how it works.

Type Safety

Use built-in TComponent<TProps> type, e.g.:

import {h, TComponent} from '@ddlab/renderer';

interface ICounterProps {count: number};

const Counter: TComponent<ICounterProps> = (props) => 
    h.p(`#${props.count} visits.`);

JSX Setup

Set jsx factory function to 'h'. It is still important to import the h function in your jsx/tsx files.

Example tsconfig:

"compilerOptions": {
    "jsx": "react",
    "jsxFactory": "h"
}

Known Issues

  • withState() uses the same state object for all instances.
0.1.0

6 years ago