npm package: @hacn/hacn
Description: Hacn - a "skin" for React components using generators.
Author: Paul Johnson
Latest version: 0.0.9

# Hacn

Hacn is a way to write react components using generators and is very similar to [redux-saga](https://redux-saga.js.org). It replaces concepts like suspense, hooks and callbacks with objects called effects, which the generator yields to the hacn code:

```typescript
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:

```bash
npm install --save @hacn/hacn
```

Yarn:

```bash
yarn add @hacn/hacn
```

## Usage

To create a component pass a javascript generator to the hacn function:

```typescript
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.

```typescript
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.

```typescript
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.

```typescript
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](https://github.com/pj)

## License

This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details

## Acknowledgments

- Inspired by react hooks.
- Also inspired by algebraic effects.
- Similar to [redux-saga](https://redux-saga.js.org)
- Similar to https://github.com/Astrocoders/epitath.