Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/calmm-js/baret

Baret is a library that allows you to embed Bacon.js observables into React VDOM
https://github.com/calmm-js/baret

bacon jsx observables react reactive vdom

Last synced: 2 months ago
JSON representation

Baret is a library that allows you to embed Bacon.js observables into React VDOM

Awesome Lists containing this project

README

        

[ [≡](#contents) | [Tutorial](#tutorial) | [Reference](#reference) ]

# Baret

Baret is a library that allows you to
embed [Bacon.js](https://baconjs.github.io/) observables
into [React](https://facebook.github.io/react/) Virtual DOM. Embedding
observables into VDOM has the following benefits:
* It allows you to use
only
[functional components](https://facebook.github.io/react/docs/components-and-props.html#functional-and-class-components),
because you can then use observables for managing state
and [`ref`](https://facebook.github.io/react/docs/refs-and-the-dom.html) for
component lifetime, leading to more **_concise code_**.
* It helps you to use React in an **_algorithmically efficient_** way:
* The body of a functional component is evaluated only once each time the
component is mounted.
* This also helps you to avoid issues such as
the
[gotcha with ref](https://facebook.github.io/react/docs/refs-and-the-dom.html#caveats).
* Only elements that contain embedded observables are rerendered when changes
are pushed through observables. An update to a deeply nested VDOM element
can be an O(1) operation.

Using Baret couldn't be simpler. You just `import React from "baret"` and you
are good to go.

[![npm version](https://badge.fury.io/js/baret.svg)](http://badge.fury.io/js/baret)
[![Gitter](https://img.shields.io/gitter/room/calmm-js/chat.js.svg)](https://gitter.im/calmm-js/chat)
[![Build Status](https://travis-ci.org/calmm-js/baret.svg?branch=master)](https://travis-ci.org/calmm-js/baret)
[![Code Coverage](https://img.shields.io/codecov/c/github/calmm-js/baret/master.svg)](https://codecov.io/github/calmm-js/baret?branch=master)
[![](https://david-dm.org/calmm-js/baret.svg)](https://david-dm.org/calmm-js/baret)
[![](https://david-dm.org/calmm-js/baret/dev-status.svg)](https://david-dm.org/calmm-js/baret?type=dev)

## Contents

* [Tutorial](#tutorial)
* [Reference](#reference)
* [`baret-lift` attribute](#baret-lift)
* [`fromBacon(observableVDOM)`](#fromBacon "fromBacon: Observable VDOM -> VDOM")
* [`fromClass(Component)`](#fromClass "fromClass: Component props -> Component (Observable props)")
* [`$$ref` attribute](#ref)

## Tutorial

To use Baret, you simply import it as `React`:

```jsx
import React from "baret"
```

and you can then write React components:

```jsx
const oncePerSecond = Bacon.interval(1000).toProperty()

const Clock = () =>


The time is {oncePerSecond.map(() => new Date().toString())}.

```

with VDOM that can have embedded [Bacon.js](https://baconjs.github.io/)
observables.

**NOTE:** The result, like the `Clock` above, is *just* a React component. If
you export it, you can use it just like any other React component and even in
modules that do not import `baret`.

## Reference

### [≡](#contents) [`baret-lift` attribute](#baret-lift)

Baret only lifts built-in HTML elements implicitly. The `baret-lift` attribute
on a non-primitive element instructs Baret to lift the element.

For example, you could write:

```jsx
import * as RR from "react-router"
import React from "baret"

const Link1 = ({...props}) =>
```

to be able to use `Link1` with
embedded [Bacon.js](https://baconjs.github.io/) observables:

```jsx
elem && elem.focus()}>
{Bacon.sequentially(1000, [3, 2, 1, "Boom!"])}

```

Note that the `ref` attribute is only there as an example to contrast
with [`$$ref`](#ref).

### [≡](#contents) [`fromBacon(observableVDOM)`](#fromBacon "fromBacon: Observable VDOM -> VDOM")

`fromBacon` allows one to convert a Bacon observable of React elements into a
React element. It is useful in case the top-most element of a component depends
on a Bacon observable.

For example:

```jsx
import {fromBacon} from "baret"
import {ifte} from "baret.util"

const Chosen = ({choice}) =>
fromBacon(ifte(choice, , ))
```

Here `ifte` from `baret-util` returns an observable that is `` when
`choice` is true and otherwise ``.

Note that the point of using `fromBacon` in the above example is that we don't
want to wrap the `ifte(...)` inside an additional element like this:

```jsx
const Chosen = ({choice}) =>


{ifte(choice, , )}

```

### [≡](#contents) [`fromClass(Component)`](#fromClass "fromClass: Component props -> Component (Observable props)")

`fromClass` allows one to lift a React component.

For example:

```jsx
import * as RR from "react-router"
import {fromClass} from "baret"

const Link2 = fromClass(RR.Link)
```

**WARNING:** A difficulty with lifting components is that you will then need to
use the [`$$ref`](#ref) attribute, which is not necessary when
using [`baret-lift`](#baret-lift) to lift an element.

#### [≡](#contents) [`$$ref` attribute](#ref)

The `$$ref` attribute on an element whose component is lifted using `fromClass`

```jsx
elem && elem.focus()}>
{Bacon.sequentially(1000, [3, 2, 1, "Boom!"])}

```

does the same thing as the ordinary
JSX
[`ref` attribute](https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute):
JSX/React treats `ref` as a special case and it is not passed to components, so
a special name had to be introduced for it.