1.5.2 • Published 5 years ago

@atomico/core v1.5.2

Weekly downloads
-
License
ISC
Repository
github
Last release
5 years ago

@atomico/core

CircleCI npm gzip

It is a small library based on the React API, but with a size as small as Preact, focused on covering components such as functions, HoCs, hooks and web-components.

Example

  1. Installation
  2. Components and Web-components
  3. Components
  4. Web-components
    1. Return rule
    2. Web-component as function
    3. Web-component as a class
  5. Api homologated by React
    1. useState
    2. useEffect
    3. useReducer
    4. useMemo
    5. useRef
  6. Hooks for web-components
    1. useHost
  7. Benefits of Atomico
  8. Examples
    1. Atomico + Web-componets + PWA

Installation

# run
npm init @atomico

? Project Type # You must select a type of project
1. Create Aplication # allows the development of apps, with support of:
				   # dynamic modules, Typescript,
				   # WebComponents, PWA and Karma.
2. Create web-component # Create a WebComponent to be shared by NPM, with support of:
					  # dynamic modules, Typescript,
					  # WebComponents, PWA and Karma.
3. Exit # Escape the CLI

Components and Web-components

Atomico allows a mixed components and web-components, only using functions, some small differences, for example if you declare web-components, this should always return the tag <host/>.

Why mixed?

The components as functions, can manage DOM or logic vs the web-components that explicitly must redo DOM.

The benefit of this is that you can apply high order components (HoCs) to build complex reusable logic structures invisible to the DOM, such as routers or more.

Components

The components that represent DOM or logic, you can use the hooks to control effects, such as updates, asynchronous waiting or more.

function Emoji({ children }) {
	let [show, setState] = useState(0);
	return (
		<div>
			<button onClick={() => setState(!show)}>toggle</button>
			{show && "😃"}
		</div>
	);
}

🔗 link example

Web components

Atomico simplifies the generation of web-components, these are declared by a function with a return rule, these should always return the tag <host>.

Return rule

All web-components declared must always return the <host/> tag, this return must be respected even if you apply high-order components.

Web-component as function

import { useEffect } from "@atomico/core";
import { h, customElement } from "@atomico/element";

function MyWebComponent(props) {
	useEffect(() => console.log("mounted"));
	return (
		<host shadowDom>
			<h1>{props.title}</h1>
			<slot />
		</host>
	);
}

MyWebComponent.observables = {
	title: String
};

customElement("my-web-component", MyWebComponent);

🔗 link example

Web-component as a class

This is a traditional approach, Element is an extension of HTMLElement, the benefit of this type of statement is that you should not use bind on the functions associated with events. You can use the hooks within render

import { h, Element, customElement } from "@atomico/element";

class MyWebComponent extends Element {
	static observables = { show: Boolean };
	toggle() {
		this.show = !this.show;
	}
	render() {
		return (
			<host shadowDom>
				<button onClick={this.toggle}>toggle</button>
				{this.show && "😃"}
			</host>
		);
	}
}

customElement("my-wc", MyWebComponent);

Api homologated by React

useState

let [state, setState] = useState(0);

Doc. from React, Identical behavior.

useEffect

useEffect(effect);

Doc. from React, Similar behavior, but Atomico optionally adds support to the use of asynchronous functions.

option 1

useEffect(()=>{
	fetch("//api")...
})

option 2

useEffect(async ()=>{
	await fetch("//api")...
})

useEffect, supports a second parameter type array, which allows to compare between renders the immutability of these, if there is a change useEffect will be executed again.

useEffect(() => {
	// This callback is only executed when props.value changes as immutable
}, [props.value]);

useEffect, allows to execute an effect cleaning function through the return of a function.

useEffect(() => {
	window.addEventListener("click", handler);
	return () => {
		// This callback is only executed once the component is deleted from the document
		window.removeEventListener("click", handler);
	};
}, []); // <<<<

useReducer

let [state, dispatch] = useReducer(reducer, initialState);

Doc. from React, Atomico has not added support to the third parameter about useReducer.

useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.

const initialState = { count: 0 };

function reducer(state, action) {
	switch (action.type) {
		case "increment":
			return { count: state.count + 1 };
		case "decrement":
			return { count: state.count - 1 };
		default:
			throw new Error();
	}
}

function Counter() {
	const [state, dispatch] = useReducer(reducer, initialState);
	return (
		<host>
			Count: {state.count}
			<button onClick={() => dispatch({ type: "increment" })}>+</button>
			<button onClick={() => dispatch({ type: "decrement" })}>-</button>
		</host>
	);
}

useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useMemo it will only recalculate the memorized value when one of the dependencies has changed. This optimization helps avoid costly calculations in each render.

useRef

const refContainer = useRef(initialValue);

useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist throughout the component's lifetime.

Hooks for web-components

useHost

Returns a ref object, which allows to extract extract the web-component, it is ideal for the construction of hooks that interact with the web-components directly, 🔗 example

Benefits of Atomico

tree shaking

Atomico has a weakly coupled api, favoring the generation of small bundles, thanks to the tree shaking process.

Size(Gzip)Groupexports
1.7kBvirtual-dom{ h, render, options, toList }
1.0kBhooks{ useState, useEffect, useMemo, useReducer, useHost }
1.0kBweb-component{ customElement }

Memo by default in all components

If you are already a React user you may know React.memo, this allows you to update only when one of its properties changes as immutable, this technique is known as Memoization(https://en.wikipedia.org/wiki/ Memoization), Atomico applies this to all components.

function Style(props) {
	useEffect(() => {
		console.log("re-render");
	});
	return <style>{props.children}</style>;
}

function MyWebComponent(props) {
	useEffect(() => console.log("mounted"), []);
	let ref = useHost();
	return (
		<host shadowDom>
			<Style>{`
      :host{padding:3rem;display:block}
      input{padding:.5rem 1rem;border-radius:5px;border:none}
      `}</Style>
			<h1>{props.title}</h1>
			<input
				value={props.title}
				onInput={({ target }) => {
					ref.current.title = target.value;
				}}
			/>
			<slot />
		</host>
	);
}

🔗 link example

Regardless of the number of times the web-component is updated, the Style component will be ignored by the diff process since its children do not change.

1.5.2

5 years ago

1.5.1

5 years ago

1.5.0

5 years ago

1.4.2

5 years ago

1.4.1

5 years ago

1.4.0

5 years ago

1.3.13

5 years ago

1.3.11

5 years ago

1.3.10

5 years ago

1.3.9

5 years ago

1.3.8

5 years ago

1.3.7

5 years ago

1.3.6

5 years ago

1.3.5

5 years ago

1.3.4

5 years ago

1.3.3

5 years ago

1.3.2

5 years ago

1.3.1

5 years ago

1.3.0

5 years ago

1.2.6

5 years ago

1.2.5

5 years ago

1.2.4

5 years ago

1.2.3

5 years ago

1.2.2

5 years ago

1.2.1

5 years ago

1.2.0

5 years ago

1.1.0

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago