Hacn
Hacn is a way to write react components using generators and is very similar to redux-saga. It replaces concepts like suspense, hooks and callbacks with objects called effects, which the generator yields to the hacn code:
import { _continue, json } from "@hacn/hacn";
const Test = function* () {
// Render the loading message without suspending.
yield _continue(<div>Loading...</div>);
// Load the data from the url and suspend waiting for the result.
const result = yield json`https://jsonplaceholder.typicode.com/todos/1`;
// render result suspending.
yield (
<div>
<div>{result.id}</div>
<div>{result.title}</div>
<div>{result.completed}</div>
</div>
);
};
See this blogpost for more: https://dev.to/pj/hacn-react-components-using-javascript-generators-88a
Installation
Install with npm or yarn:
Npm:
npm install --save @hacn/hacn
Yarn:
yarn add @hacn/hacn
Usage
To create a component pass a javascript generator to the hacn function:
import React from "react";
import ReactDOM from "react-dom";
import {} from "@hacn/hacn";
const Test = function* () {
yield <div>Hello World!</div>;
};
ReactDOM.render(<Test />, document.getElementById("root"));
Examples
Show loading message while fetching data.
This example displays a loading message before waiting for a data fetch to complete, before displaying the returned data.
import { _continue, json } from "@hacn/hacn";
const Test = function* () {
// Render the loading message without suspending.
yield _continue(<div>Loading...</div>);
// Load the data from the url and suspend waiting for the result.
const result = yield json`https://jsonplaceholder.typicode.com/todos/1`;
// render result suspending.
yield (
<div>
<div>{result.id}</div>
<div>{result.title}</div>
<div>{result.completed}</div>
</div>
);
};
Capture DOM events
This example shows using the capture parameter to return events from the render.
import {} from "@hacn/hacn";
const Test = function* (props, capture) {
let enteredText = "";
while (enteredText !== "hello") {
// Render, capturing the onChange event as a value to return.
const changeEvent = yield (
<div>
{'Enter "hello":'}:
<input
type="text"
name="hello"
value={enteredText}
onChange={capture}
/>
</div>
);
enteredText = changeEvent.target.value;
}
yield <div>hello to you to!</div>;
};
Handling render errors
Errors are thrown and can be captured like normal.
import {} from "@hacn/hacn";
const ErroringComponent = (props: any) => {
throw new Error("This component has errors");
};
const Test = function* () {
try {
yield <ErroringComponent />;
} catch (e) {
yield <div>An error occurred: {e.message}</div>;
}
};
Authors
- Paul Johnson - pj
License
This project is licensed under the MIT License - see the LICENSE.md file for details
Acknowledgments
- Inspired by react hooks.
- Also inspired by algebraic effects.
- Similar to redux-saga
- Similar to https://github.com/Astrocoders/epitath.