# Read Me

&#x20;[![](https://4207814760-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LK69xjEUCbmndMAXers%2F-LQQZne0ALbpCUob8Yi2%2F-LQQZofZ_zjksGG-ZYAe%2Frefract-logo-colour.png?generation=1541282165290485\&alt=media)](/)<br>

&#x20;Handle your component effects and side-effects in a clear and declarative fashion\
&#x20;by using asynchronous data streams (reactive programming). <br>

&#x20;[**Why?**](/#why) · [**Install**](/#installation) · [**The Gist**](/#the-gist) · [**Learn**](/#learn-refract) · [**Contribute**](/#contributing) · [**Discuss**](/#discuss) <br>

&#x20;[![Build](https://travis-ci.org/fanduel-oss/refract.svg)](https://travis-ci.org/fanduel-oss/refract) [![MIT License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Styled with Prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier) <br>

* 🎳 **Decentralised**: attach effects and side-effects to your components, for better code splitting results
* 🌅 **Gradual**: use on an existing component today, throughout your app tomorrow
* 🚀 **Reactive**: leverage the power and benefits of reactive programming
* 💾 **Tiny**: less than 2Kb minified and gzipped
* ✏ **Typed**: written in TypeScript, fully typed integrations
* ⚡ **Universal**: supports React, React Native, Inferno and Preact

Refract makes reactive programming possible in React, React Native, Preact and Inferno, with only a single higher-order component or a single hook! You can choose to start using a tiny bit of reactive programming, or go full reactive. Refract allows you to:

* [Manage side effects](https://refract.js.org/usage/getting-started) like API calls, analytics, logging, etc.
* [Manipulate, replace and inject props](https://refract.js.org/usage/pushing-to-props), you can even [fully replace Redux `connect` HoC](https://refract.js.org/recipes/replacing-connect)
* [Handle state](https://refract.js.org/recipes/handling-state)
* [Render components](https://refract.js.org/usage/rendering-components)

We also provide a Redux integration, which can serve as a template for integrations with other libraries. With a single HoC, you can fully replace libraries like [recompose](https://github.com/acdlite/recompose), [redux-observable](https://redux-observable.js.org/), and [react-redux](https://github.com/reduxjs/react-redux) to name a few!

## Why?

Component-based architecture and functional programming have become an increasingly popular approach for building UIs. They help make apps more predictable, more testable, and more maintainable.

However, our apps don't exist in a vacuum! They need to handle state, make network requests, handle data persistence, log analytics, deal with changing time, and so on. Any non-trivial app has to handle any number of these effects. Wouldn't it be nice to cleanly separate them from our apps?

Refract solves this problem for you, by harnessing the power of reactive programming. [For an in-depth introduction, head to `Why Refract`.](https://refract.js.org/introduction/why-refract)

## Installation

Refract is available for a number of reactive programming libraries. For each library, a Refract integration is available for React, Inferno, Preact and Redux.

Available packages:

|                                                   | [React](https://github.com/facebook/react) | [Inferno](https://infernojs.org/) | [Preact](https://preactjs.com/) | [Redux](https://github.com/reduxjs/redux) |
| ------------------------------------------------- | ------------------------------------------ | --------------------------------- | ------------------------------- | ----------------------------------------- |
| [**Callbag**](https://github.com/callbag/callbag) | refract-callbag                            | refract-inferno-callbag           | refract-preact-callbag          | refract-redux-callbag                     |
| [**Most**](https://github.com/cujojs/most)        | refract-most                               | refract-inferno-most              | refract-preact-most             | refract-redux-most                        |
| [**RxJS**](https://github.com/reactivex/rxjs)     | refract-rxjs                               | refract-inferno-rxjs              | refract-preact-rxjs             | refract-redux-rxjs                        |
| [**xstream**](https://github.com/staltz/xstream)  | refract-xstream                            | refract-inferno-xstream           | refract-preact-xstream          | refract-redux-xstream                     |

To use the latest stable version, simply `npm install` the package you want to use:

```
npm install --save refract-rxjs
```

## The Gist

The example below uses `refract-rxjs` to send data to localstorage.

Every time the `username` prop changes, its new value is sent into the stream. The stream debounces the input for two seconds, then maps it into an object (with a `type` of `localstorage`) under the key `value`. Each time an effect with the correct type is emitted from this pipeline, the handler calls `localstorage.setItem` with the effect's `name` and `value` properties.

```javascript
const aperture = component => {
    return component.observe('username').pipe(
        debounce(2000),
        map(username => ({
            type: 'localstorage',
            name: 'username',
            value: username
        }))
    )
}

const handler = initialProps => effect => {
    switch (effect.type) {
        case 'localstorage':
            localstorage.setItem(effect.name, effect.value)
            return
    }
}

const WrappedComponent = withEffects(aperture, { handler })(BaseComponent)
```

The example demonstrates uses the two building blocks used with Refract - an `aperture` and a `handler` - and shows how they can be integrated into a React component via the `withEffects` higher-order component.

#### Aperture

An `aperture` controls the streams of data entering Refract. It is a function which observes data sources within your app, passes this data through any necessary logic flows, and outputs a stream of `effect` values in response.

#### Handler

A `handler` is a function which causes side-effects in response to `effect` values.

## Learn Refract

### Documentation

Documentation is available at [refract.js.org](https://refract.js.org). We aim to provide a helpful and thorough documentation: all documentation files are located on this repo and we welcome any pull request helping us achieve that goal.

### Examples

We maintain and will grow over time a set of examples to illustrate the potential of Refract, as well as providing reactive programming examples: [refract.js.org/examples](https://refract.js.org/examples).

Examples are illustrative and not the idiomatic way to use Refract. Each example is available for the four reactive libraries we support (RxJS, xstream, Most and Callbag), and we provide links to run the code live on [codesandbox.io](https://codesandbox.io). All examples are hosted on this repo, and we welcome pull requests helping us maintaining them.

## Contributing

#### Guidelines

We welcome many forms of contribution from anyone who wishes to get involved.

Before getting started, please read through our [contributing guidelines](https://github.com/fanduel-oss/refract/tree/156172190873a18ba9f2df9d0e6dc3f5a5b96463/CONTRIBUTING.md) and [code of conduct](https://github.com/fanduel-oss/refract/tree/156172190873a18ba9f2df9d0e6dc3f5a5b96463/CODE_OF_CONDUCT.md).

## Links

#### Logo

[The Refract logo is available in the Logo directory](https://github.com/fanduel-oss/refract/tree/156172190873a18ba9f2df9d0e6dc3f5a5b96463/logo/README.md).

#### License

[Refract is available under the MIT license.](https://github.com/fanduel-oss/refract/tree/156172190873a18ba9f2df9d0e6dc3f5a5b96463/LICENSE/README.md)

#### Discuss

[Everyone is welcome to join our discussion channel - `#refract` on the Reactiflux Discord server.](https://discord.gg/fqk86GH)

#### Talks

* [ReactiveConf 2018 - Thomas Roch: **Be More Functional and Reactive in React**](https://www.youtube.com/watch?v=c8p9o4rxcYk)
* [ReactiveConf 2018 - **AMA w/ Thomas Roch**](https://www.youtube.com/watch?v=liqHgQz8Ar0)

#### Articles

* [The introduction to Reactive Programming you've been missing](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754) by [@andrestaltz](https://twitter.com/andrestaltz)
* [SurviveJS Interview with Thomas Roch - Refract: Manage Component Side Effects the Reactive Way](https://survivejs.com/blog/refract-interview/)
* [How we harnessed the power of reactive programming with Refract](https://medium.freecodecamp.org/how-we-harnessed-the-power-of-reactive-programming-with-refract-87f269ac779e)


# Introduction

* [Why Refract](/introduction/why-refract)
* [Core Concepts](/introduction/core-concepts)
* [Thinking In Refract](/introduction/thinking-in-refract)
* [Alternatives](/introduction/alternatives)


# Why Refract?

As JavaScript applications have matured, it has become clear that there is a conflict at their heart.

The ideal we aim for is a **composable component-based architecture**, using functional programming principles and unidirectional data flow. The benefits of this ideal are apps which are **more predictable, more testable, and more maintainable**.

However, once your app needs to include side-effects such as event handling, API requests or analytics, this purity becomes impossible. These side-effects hold us back from writing fully declarative code. Wouldn't it be nice to cleanly separate them from our apps, so that we can achieve our ideal inside our apps while still connecting to the outside world?

On the other hand, reactive programming has demonstrated how powerful it is to handle synchronous and asynchronous logic in a declarative manner. Refract is possibly the first general-purpose abstraction to fully leverage reactive programming with React (and Preact and Inferno).

**Refract allows you to manage your application logic and effects declaratively and reactively.** You can start to use it gradually today, for managing some side-effects, without changing the way you write components or the libraries you use. As you become more comfortable with Refract and reactive programming, you will be able to take it all the way to write fully reactive React applications!


# Core Concepts

With functional programming and components becoming an increasingly popular option for building UIs, we've become used to unidirectional data flows, view / state separation and immutable data.

```
               +------------+
         +----->   State    +-----+
         |     +------------+     |
Setter / |                        | Getter /
Action   |                        | Selector
         |     +------------+     |
         +-----+    View    <-----+
               +------------+
```

However, the loop above doesn't exist in a vacuum! Various external effects compose the business logic of an app: network requests, time, data persistence, analytics, etc. State mutations (`setState`, reducers), state getters and render functions are in principle always pure. As a result, interaction handlers such as `onClick` or lifecycle methods such as `componentDidMount` handle side-effects imperatively.

## Separation of concerns

Refract allows you to cleanly separate concerns in your app: you can extract effects and side-effects into their own functions. We tend to distinguish side-effects (things happening outside your application: analytics, data persistance, ...) from effects (things happening inside your application: network requests, dispatching to a store, mapping or replacing props, ...).

### Side-effects

Your application should be able to function with or without its side-effects: for instance, how many times have you experienced a website not working? Only to realise that your ad blocker had blocked a third party script, causing a missing analytic function to crash the whole app!

With Refract, you can wrap side-effects around your container components, and ensure that your application works with or without them.

### Effects

For effects, your application shouldn't be able to function without them. For instance, you can look at the [typeahead example](/examples/typeahead): without input debouncing and network requests, the input component would lose its main functionality.

In the case of effects, Refract helps you separate them into different logical units, increasing maintainability of your apps and promoting code re-use. Read [Thinking in Refract](/introduction/thinking-in-refract) for a more detailed explanation.

## Paradigms

Refract makes use of functional and reactive principles to manage effects and side-effects. Reactive programming especially is extremely powerful in its ability to chain time-based operations without breaking a sweat: Refract offers a great way to gradually use it in component-based applications (React, Inferno and Preact).

### Functional and declarative

Perhaps this is familiar:

```javascript
const setFilter = (name, value) => {
    setState({
        [name]: value
    })

    window.localStorage.setItem(name, value)
    myAnalyticsProvider.logEvent('FilterChange', {
        [name]: value
    })
}
```

The side-effects of persisting the filter value and firing an analytics event are imperative: they are concerned with the "what" as well as the "how".

```javascript
const declarativeStorageSideEffect = (name, value) => ({
    type: 'localStorage',
    name,
    value
})

const imperativeSideEffectHandler = effect => {
    if (effect.type === 'localStorage') {
        window.localStorage.setItem(name, value)
    }
}
```

`declarativeStorageSideEffect` is pure while `imperativeSideEffectHandler` is not. Every application will have imperative and impure code: `declarativeStorageSideEffect` can't exist without `imperativeStorageSideEffect`. But it is best for imperative code to be isolated and as high as possible in your application.

Declarative side-effects have two main benefits:

* easier to test (pure functions)
* only one place is concerned with the "how" (imperative code)

### Reactive

The key to reactive programming is observability: we need to be able to observe changes in your app, get notified when they happen so we can trigger side-effects. Reactive programming works really well for side-effects: side-effects are just data. It is also a remarkable abstraction encouraging declarative programming and which can concisely express time-based operations (throttle, debounce, etc.).

We have seen a lot of side-effect management libraries in Redux, due to the observability of its actions (with middleware). It is entirely possible to move side-effects handling to React, and to not have to rely on Redux.

To see how Refract compares to other side-effects libraries, check our [comparison guide](/introduction/alternatives). To see Refract usage, head to [using Refract](/usage/getting-started).


# Thinking In Refract

Refract differs from the typical mental model used for React applications. It requires you to adapt your mental model to:

* think in reactive programming
* systematically think through effects

Thinking reactive will help you think through effects and *vice versa*. This change of paradigm requires time, but fortunately Refract can be adopted gradually: you can initially use it where it is most obvious, and discover over time more and more use cases.

## Thinking reactive

Reactive programming is renowned for being challenging to learn. It requires a different mental model and the vast majority of us have been wired to think of our code imperatively.

Reactive programming isn't more complicated than the rest, but it requires time for your brain to slowly transition to this paradigm. There are more and more resources available online to learn reactive programming, but we recommend [The introduction to Reactive Programming you've been missing ](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754).

If you are new to reactive programming or don't have a library of choice yet, we recommend you look at the different libraries we offer bindings for (RxJS, xstream, Most, callbag) and choose the one you are most comfortable with.

## Thinking through effects

Being able to systematically think through effects also requires a change in how you conceive what happens in your application. Mainly, it lets us think about state transitions rather than state.

Instead of thinking *"While x is going on, y should be in that state"*, you need to think *"When x happens, y should transition to that state"*. Let's put this into perspective with a simple example: a registration form. Your form needs to contain the following elements:

* A username field which needs to make sure the chosen value isn't already taken.
* A submit button which sends a request to an API. While the request is being processed, the form should not be editable.

When not thinking through effects, we would make the following statements:

* When a user types characters in the username field, network requests need to be performed to validate the chosen username, while the submitted button is disabled.
* When a user clicks on the submit button, the username value should be posted to the API, while both the submitted button and username field are disabled.

Thinking through effects requires you to isolate each action or event from their resulting effect:

* On each new character typed in the username field, the form status should transition to 'validating'
* When the form status transitions to 'validating', the submit button should be disabled
* When the form status transitions to 'validating', a network request should be made to the API for validating the chosen username
* When a request to validate the chosen username is sent, any previous request should be cancelled
* When the username validation response is received, the form validation status should be updated
* When the submit button is clicked, the form status should transition to 'ready'
* When the form status transitions to 'ready', the form should be disabled
* When the form status transitions to 'ready', a create user request should be sent to the API
* When a successful create user response is received from the API, the app should navigate away
* When a non successful create user response is received from the API, the form should be enabled AND an error message should be displayed

Thinking through effects actually allows you to decompose any problem in small and discrete pieces.


# Alternatives

There are a number of alternative solutions for managing effects, most of which are focused on Redux. Typically, they allow you to observe actions dispatched to the store, and encourage you to only dispatch new actions as a side-effect. The most popular libraries are `redux-observable` and `redux-saga`.

There are also a number of libraries which offer ways to leverage Reactive programming with React, like `recompose` or `recycle`.

Refract takes a unique approach. It aims to provide a generalised approach to observing all data within your app, and managing any effects needed, by leveraging reactive programming. It colocates this logic with your components, which provides further advantages.

The benefits of Refract are:

1. **It can observe any source of data** - Component props, Redux actions, Redux state, any data source in your app.
2. **It can define any effect** - besides built-in effects (mapping to props, replacing props and rendering), you are fully in control of what can be done and how it is expressed.
3. **It colocates effects with your components** - they only run when your components run, which is great for code splitting and performance.
4. **It leverages existing reactive programming libraries** - you can choose from `RxJS`, `xstream`, `most`, and `callbag`, with no need to learn a domain-specific language. For each library, Refract provides strong type definitions.
5. **It doesn't prescribe a state container solution.**
6. **It uses React props for dependency injection.**

In our experience, Refract offers advantages in comparison to all libraries named below, with the exception of `redux-cycles`: Refract can achieve similar results to `redux-cycles`.

## redux-thunk

[Thunks](https://redux.js.org/api-reference/applymiddleware#example-using-thunk-middleware-for-async-actions) can be used to express any side-effect imperatively, and to dispatch to your store asynchronously.

It is a good way to get started before making a choice on what abstraction and side-effect model to use. There is nothing wrong in sticking to thunks!

## redux-saga

[Redux-saga](https://redux-saga.js.org/) is a powerful solution to express effects, and is the leader in its space.

However, like similar redux-based solutions, it is designed for observing actions and dispatching actions as a result, and other uses are either unsupported or discouraged. "Sagas" can be added dynamically, but they can't be removed.

Redux-saga introduces its own DSL and time-based operators. The learning curve is steep, it adds size to your project, and it is not re-usable outside Redux.

## redux-observable

[Redux-observable](https://redux-observable.js.org/) is similar to redux-saga and offers another powerful solution.

Like redux-saga, it is also designed for action-to-action effects. It is possible to dynamically add "epics", but it isn't possible to remove any.

It leverages RxJS for declaring effects, so the learning curve is also steep, and it is not re-usable outside Redux.

Redux-observable allows you to use other reactive libraries (xstream, most) but only on top of RxJS, which is unfortunately included by default.

## redux-loop

[Redux-loop](https://redux-loop.js.org/) embeds side-effect logic in your reducers.

It is not limited to reacting to actions and you can also react to state changes. However, effects can only be actions, and it adds complexity to your reducers. It comes with the disadvantage of not separating concerns of state mutation and side-effects. It is also inherently tied to Redux.

Redux-loop is not as powerful as redux-saga or redux-observable with time-based effects.

## redux-cycles

[Redux-cycles](https://github.com/cyclejs-community/redux-cycles) is a Cycle.js-based solution which adds Redux observability. It benefits from the mighty power of Cycle.js and its declarative and reactive architecture. It leverages reactive programming and can be used with various libraries (most, RxJS, xstream), but requires xstream by default.

## react-side-effect

[React-side-effect](https://github.com/gaearon/react-side-effect) allows declarative side-effects within React, by reacting to prop changes. It is a great solution for basic needs. While it shares similarities with Refract, it cannot react to prop functions being called. It is also not able to create time-based effects, and side-effects can't use props (no dependency injection).

## recycle

[Recycle](https://github.com/recyclejs/recycle) is an abstraction built on top of React which enables the use of reactive programming (RxJS) for handling state and effects.

## recompose

[Recompose](https://github.com/acdlite/recompose/blob/master/docs/API.md) is a React library providing various higher-order components and utilities. The HoCs provided by recompose are specialised and allow to manipulate props and handle state. It offers observable utilities to handle props and rendering reactively.


# Usage

* [Getting Started](/usage/getting-started)
* [Installation](/usage/installation)
* [Connecting To React](/usage/connecting-to-react)
* [Observing React, Preact and Inferno](/usage/observing-react)
* [Injecting Dependencies](/usage/injecting-dependencies)
* [Observing Redux](/usage/observing-redux)
* [Observing Anything](/usage/observing-anything)
* [Handling Effects](/usage/handling-effects)
* [Pushing to Props](/usage/pushing-to-props)
* [Rendering Components](/usage/rendering-components)
* [Handling Errors](/usage/handling-errors)
* [Testing](/usage/testing)


# Getting Started

The usage section of the docs explores the intended use of Refract, focusing on each concept or feature in isolation.

If you are unfamiliar with reactive programming, we recommend reading Andre Staltz's article [The introduction to Reactive Programming you've been missing](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754) before reading these docs. Reactive programming is central to Refract, so some understanding of the paradigm will be essential.

Before we begin, below is a quick explanation of some new terms associated with Refract which we will use throughout the documentation.

Each will be more thoroughly explored through examples, but starting with a rough approximation in mind will help.

## Aperture

An `aperture` controls the streams of data which enter Refract.

It is a function which observes data sources within your app, passes this data through any necessary logic flows, and outputs a stream of `effect` values in response.

## Handler

A `handler` is a function which causes side-effects in response to any `effect` value output by the `aperture`.

## Error Handler

An `errorHandler` is a function which causes side-effects in response to any `error` value output by the `aperture`.


# Installation

Refract is available for a number of reactive programming libraries. For each library, a Refract integration is available for React, Inferno, Preact and Redux.

Available packages:

|                                                   | [React](https://github.com/facebook/react) | [Inferno](https://infernojs.org/) | [Preact](https://preactjs.com/) | [Redux](https://github.com/reduxjs/redux) |
| ------------------------------------------------- | ------------------------------------------ | --------------------------------- | ------------------------------- | ----------------------------------------- |
| [**Callbag**](https://github.com/callbag/callbag) | refract-callbag                            | refract-inferno-callbag           | refract-preact-callbag          | refract-redux-callbag                     |
| [**Most**](https://github.com/cujojs/most)        | refract-most                               | refract-inferno-most              | refract-preact-most             | refract-redux-most                        |
| [**RxJS**](https://github.com/reactivex/rxjs)     | refract-rxjs                               | refract-inferno-rxjs              | refract-preact-rxjs             | refract-redux-rxjs                        |
| [**xstream**](https://github.com/staltz/xstream)  | refract-xstream                            | refract-inferno-xstream           | refract-preact-xstream          | refract-redux-xstream                     |

The examples below assume you're using `RxJS` - if you're using a different library, use the table above to find the correct package names.

## React, Inferno and Preact Packages

The React, Inferno and Preact packages don't require much set up - you just need to install the package (usually via `npm` or `yarn`):

```
npm install --save refract-rxjs
```

The same applies to Inferno and Preact packages.

## Redux Packages

The Redux packages involve an extra step to apply the Refract enhancer to your Redux store:

1. Install the latest stable version (again usually via `npm` or `yarn`):

   ```
   npm install --save refract-redux-rxjs
   ```
2. Import the Refract store enhancer and apply it to your redux store. This process is explained in detail in the Redux documentation: [Configuring your store](https://redux.js.org/recipes/configuring-your-store).

   For example:

   ```javascript
   import { compose, createStore } from 'redux'
   import { refractEnhancer } from 'refract-redux-rxjs'

   import reducers from './store'

   const store = createStore(reducers, {}, refractEnhancer())

   export default store
   ```

   *(Note that this example is unrealistically simple!)*


# Connecting To React

> This document focuses on React, but the same applies to Inferno and Preact

## Background

Refract builds upon two ideas which have been embraced by the React community: `separating presentational and container components`, plus `higher-order components` (HoCs).

If you're unfamiliar with these concepts, the best places to start are [Dan Abramov's article explaining presentational/container components](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0), and the [React documentation page explaining HoCs](https://reactjs.org/docs/higher-order-components.html). These concepts are important, and will help you build more scalable applications, so don't skip those links!

## Where Refract Belongs

The key insight behind presentational/container components is that your application's `state` and its `view` should be separated. In React, your state is typically passed into your view as props.

Refract sits between your state and your view, allowing you to observe the changes to those props over time. To achieve this, you simply wrap your view with Refract's `withEffects` higher-order component.

For example, given a simple view component:

```javascript
const Counter = ({ count, increment }) => (
    <button onClick={increment}>Count: {count}</button>
)
```

If we want to cause side-effects in response to changes in the props being passed into our `Counter`, we use `withEffects` to create an enhanced version of the component:

```javascript
import { withEffects } from 'refract-rxjs'

// Note that the handler and aperture are explained later in the docs,
// these empty functions are just placeholders
const aperture = (component, initialProps) => {}
const handler = initialProps => effect => {}
//

const CounterWithEffects = withEffects(aperture, { handler })(Counter)
```

This new `CounterWithEffects` component now includes the side-effect logic included in our `handler` and `aperture`, and renders the original `Counter` presentational component unaltered. It can be used just like any other component:

```javascript
class Container extends Component {
    state = { count: 0 }

    increment = () => this.setState(({ count }) => ({ count: count + 1 }))

    render() {
        return (
            <CounterWithEffects
                count={this.state.count}
                increment={this.increment}
            />
        )
    }
}
```


# Observing React, Preact and Inferno

> This document focuses on React, but the same applies to Inferno and Preact
>
> A Refract hook is available in version 2.3.0-alpha.0. API is similar except functions cannot be observed. For more detail, see [useRefract API](/api/userefract)

Refract exposes an object called `component` as your `aperture`'s first argument, which allows you to cause side-effects in response to changes within your React app.

```javascript
const aperture = component => {
    /* ... */
}
```

This `component` object contains three properties: `observe`, `mount`, and `unmount`. The `observe` property is a function which let you observe your React props. The `mount` and `unmount` properties are streams which let you observe your React component's lifecycle.

## Example

The explanations below are all based on changing the `aperture` in the following example to observe different things:

```javascript
import React, { useState } from 'react

const Input = ({ value, onChange }) => (
    <input value={value} onChange={onChange} />
)

const InputWithEffects = withEffects(aperture, { handler })(Input)

const Container = () => {
    const [currentValue, setValue] = useState('')

    return (
        <InputWithEffects
            value={currentValue}
            onChange={newValue => setValue(newValue)}
            {...otherProps}
        />
    )
}
```

## Observing Props

Refract's `component.observe` function lets you observe your React props. It handles three different use cases: observing values, observing functions, and observing all props.

`component.observe` takes two optional arguments:

* `propName` *(string)*: an optional string, the name of the prop which you wish to observe.
* `propTransformer` *(function)*: an optional function to transform each received value of `propName`

```javascript
const aperture = component => {
    const onChange$ = component.observe('onChange')
    const value$ = component.observe('value')
    /* create effects here */
}
```

When observing values, the returned stream is initialised with the current observed prop value. If you wish to only observe subsequent changes, you can "drop" the first value: search for a `drop` operator in the reactive programming library you use.

### Observing Values

Values are the primitive props you pass into your components: numbers, strings, booleans, objects, etc.

When the prop you observe is a value, `component.observe` will return a stream of this prop's values as it changes over time.

Refract emits new prop values only if they have changed. The change detection is done using reference equality `===` - if you need a different change detection mechanism (to exclude more values), it is easy to filter them using a `filter` operator.

For example, if we want to observe the `value` prop in our aperture, and only cause an effect when the new string is at least five characters long:

```javascript
const aperture = component => {
    const value$ = component.observe('value')

    return value$.pipe(filter(string => string.length > 5))
}
```

Prop values can be transformed using the second argument of `observe`, and only distinct values returned by the transformer will be emitted by the returned observable. It is handy for observing nested values:

```javascript
const userName$ = component.observe('user', user => user.name)
```

### Observing Functions

Functions are the callbacks you pass into your components: any function which is passed as props, such as an onClick handler or a setState function. By default, Refract will decorate these prop functions, so you can observe arguments they are called with. You can turn this off by setting `decorateProps` to `false` in `withEffects` config object.

When the prop you observe is a function, `component.observe` will return a stream which emits a new value each time your function is called. This value will be the first argument passed to the function.

For example, if we want to observe arguments passed to the `onChange` prop to achieve the same effect as above:

```javascript
const aperture = component => {
    const onChange$ = component.observe('onChange')

    return onChange$.pipe(filter(string => string.length > 5))
}
```

This example does not significantly differ from the `value` example above (the stream won't be initialised with a value), but in more complex situations it can be extremely useful to observe arguments passed to callbacks in addition to values passed via props.

If you want to observe a function taking multiple args, you can provide a second argument to `observe`:

```javascript
const args$ = component.observe('myFunc', args => args)
// By default the first argument is pushed: args => args[0]
```

### Observing All Props

In some cases, within your `aperture` you might wish to use the current value of all your component's props. While this is possible via manually calling `component.observe('prop')` for each of the props you wish to include and then combining all of the resulting streams, this is a lot of setup for a simple feature.

Instead, when you do not specify a `propName`, `component.observe` will return a stream which emits a new object each time *any* prop changes. This object will contain all of your component's props. *(note: change detection in this case is determined by React: withEffects is implemented as a PureComponent)*

For example, if you wanted to just send all props through to your `handler` every time one of them changes:

```javascript
const aperture = component => component.observe()
```

## Observing Events

In some cases you might want to observe a particular event such as a click on an hyperlink, without having a prop to observe. You might also want to use Refract for all your application mutations and effects, without piggy backing on existing mutations.

`withEffects` injects a method `pushEvent` to your components, so you can inform Refract of events happening inside your components. We use a callback because we aim to offer a universal solution not tied to a specific renderer (web, native). That way we don't have to use refs or low-level platform-specific primitives.

### Pushing events

`pushEvent` is a curried function which takes an event name (`eventName`) and a value:

```javascript
function MyComponent({ pushEvent }) {
    return <button onClick={pushEvent('buttonClick')}>Click me!</button>
}
```

### Observing events

In your aperture, you can observe events by simply invoking `component.fromEvent`. It takes two arguments (second one is optional):

* `eventName` *(string)*: the name of the event which you wish to observe
* `eventTransformer` *(function)*: an optional function to transform the value of each `eventName` event

```javascript
const aperture = component => {
    const buttonClick$ = component.fromEvent('buttonClick')

    return buttonClick$.pipe(mapTo('Button clicked!'))
}
```

### Using events

A convenient helper function `useEvent` is available on `component`, to make it easier to use events: it returns a tuple containing the result of `fromEvent(eventName)` and `pushEvent(eventName)`. `useEvent` takes two arguments:

* `eventName` *(string)*: the name of the event
* `seedValue` *(any)*: an optional seed value to initialise the stream of event values with

```javascript
const aperture = component => {
    const [ value$, setValue ] = component.useEvent('eventName', '')

    return value$.pipe(map(value => toProps({
        value,
        setValue
    })))
```

## Observing Lifecycle Events

The remaining two properties on the `component` object are `component.mount` and `component.unmount`.

These are streams which emit an event, like a signal, either when the component mounts or when the component unmounts.

### Observing Component Mount

`component.mount` is a stream which will emit a single value when a component mounts.

It can be useful to defer any logic until a component has been mounted.

```javascript
const aperture = component => {
    const mount$ = component.mount

    return mount$.pipe(mapTo('Component mounted!'))
}
```

### Observing Component Unmount

`component.unmount` is a stream which will emit a single value when a component unmounts.

It can be useful to trigger side-effects when a component is about to be unmounted.

```javascript
const aperture = component => {
    const unmount$ = component.unmount

    return unmount$.pipe(mapTo('Component unmounted!'))
}
```

## Combining Observations

Refract's API is designed so that you have complete, fine-grained control over your side-effects. You are encouraged to observe multiple props simultaneously (both values and functions) alongside lifecycle events.

By combining these observable sources with the power of reactive programming, you can build complex side-effect logic in a clear and declarative fashion.


# Injecting Dependencies

Refract lets you inject your own dependencies, such as your Redux store, your router, your API, and so on.

To expose any dependencies for use inside Refract, you simply pass them as props into any component wrapped with the `withEffects` higher-order component. Your dependencies will then be available as part of the `initialProps` object, which is the second argument in your `aperture`, and the first argument in your `handler` and `errorHandler`.

## Exposing Your Redux Store

In order to use Refract with Redux, you will need to expose your Redux store as a dependency to your Refract components.

To do so, simply pass your store into your component as props, exactly as you do when passing your store to the Redux Provider component:

```javascript
import { Provider } from 'redux'
import { withEffects } from 'refract-rxjs'

import configureStore from './configureStore'
import App from './components/App'

const store = configureStore()
const AppWithEffects = withEffects(aperture, { handler })(App)

ReactDOM.render(
    <Provider store={store}>
        <AppWithEffects store={store} />
    </Provider>,
    document.getElementById('root')
)
```

This pattern is likely to change in future when Redux moves to React's new context API.

## Other Dependencies

Because dependencies are simply passed into Refract as props, you can easily add any dependency you need - all you have to do is add more props!

To see an example of what a useful dependency might look like, take a look at the [API dependency recipe](/recipes/creating-an-api-dependency).

## Passing Dependencies To Children

You might have noticed a problem with the approach outlined above: how do you pass these dependencies down to any `ComponentWithEffects` which are far further down the React component tree?

A naïve approach would be to pass all dependencies down through your app as props, but that would be a pain to maintain.

Instead, we recommend using React's new context API, which is perfect for passing this kind of information through to any arbitrary child within your app.

For an explanation of how to do this, and a tip for how to make the code clean and simple, take a look at the [dependency-injection](/recipes/dependency-injection) recipe.


# Observing Redux

*Before you can observe your Redux store, make sure you have used dependency injection to expose it to your Refract components!*

Refract adds a method to your store called `observe` (see [Getting Started](/usage/getting-started)), which you can use to observe Redux from inside your `aperture`.

```javascript
const aperture = (component, initialProps) => {
    const streamFromStore$ = initialProps.store.observe('something')
}
```

`store.observe` takes one argument, which can be either a string or a function.

## Observing Actions

If you pass in a string, `store.observe` returns a stream of actions dispatched to your store which have that string as their action type.

```javascript
const aperture = (component, { store }) => {
    const ping$ = store.observe('PING')
    const pong$ = store.observe('PONG')
}
```

In this example, `ping$` will receive any action with a type of `PING` which gets dispatched to your store, and `pong$` will receive any action with a type of `PONG` which gets dispatched to your store.

Each observed action is passed into your stream with all its data - including the payload.

## Observing State

If you pass in a function, `store.observe` will treat it as a Redux selector, and return a stream which subscribes to the state using your function, initialised with the selector's current value. Any time the selected slice of state changes, its new value will be piped to your stream if changed (`===` comparison).

```javascript
const storeShape = {
    users: {
        SomeUserName: {
            balance: 999,
            ...user
        }
    }
}

const getBalance = username => state => state.users[username].balance

const aperture = (component, { store }) => {
    const balance$ = store.observe(getBalance('SomeUserName'))
}
```

In this example, `balance$` will receive a new value every time the user's balance changes.

Note that this is particularly powerful in combination with curried selectors - by tweaking the above example to use the `initialProps` to source the username, we can select the slice of state dynamically:

```javascript
const aperture = (component, { store, username }) => {
    const balance$ = store.observe(getBalance(username))
}
```

## Combining Observations

As mentioned previously, Refract's API is designed to give you complete control over your side-effects, and you are encouraged to observe multiple sources simultaneously.

Observing both actions and state is a powerful combination which opens up many opportunities for complex functionality to be implemented in a clean and maintainable way.


# Observing Anything

As explained in the [dependency injection](/usage/injecting-dependencies) documentation, you can add dependencies to your `aperture` via React props. By passing observable data sources as props, you can observe anything you wish, and trigger side-effects in response.

In addition, your `aperture` is a blank slate, and allows you to observe anything which exists in the global context such as time or events.

## Events

By using your streaming library's utilities aimed at creating observables, you can respond to any events available in JavaScript.

For example, you can observe the `window.popstate` event to respond to the user clicking back/forward in the browser:

```javascript
const aperture = component => {
    const popstate$ = fromEvent(window, 'popstate').pipe(
        map(event => ({
            type: 'POPSTATE',
            state: event.state
        }))
    )
}
```

Or as another example, you could listen to the `window.resize` event in order to dynamically alter your logic depending on the user's screen size:

```javascript
const aperture = component => {
    const resize$ = fromEvent(window, 'resize').pipe(debounce(500))
}
```

## Time

Your streaming library will also provide utilities for observing the passing of time.

For example, if you want to do something once every few seconds as a kind of background process, it's easy to create an interval stream:

```javascript
const aperture = component => {
    const interval$ = interval(4000) // emits once every four seconds
}
```

## Custom Dependencies

It's also possible to create your own dependencies with custom methods similar to our `component.observe` and `store.observe`, and expose them through dependency injection via props. If you do, please publish them so that others can use it too!


# Handling Effects

Each time an effect is piped out of your `aperture` stream pipeline (assuming no errors occur), it is passed to your `handler`.

```javascript
const handler = (initialProps) => (effect) => {
    /* handle effects here */
}
```

Similar to your `aperture`, your `handler` is passed all of your component's props through the `initialProps` object. This means that when you inject your dependencies via props, they're also available here!

This makes it easy to call imperative side-effects in your handler, as a clear and simple way to either push data back into your app after it has been through your async pipeline, or send it out to some external dependency which will not return data to your app.

## Global Handler

The internal logic of your handler can be as simple or as complex as you wish, and each Refract component can have a custom handler if you choose.

However, in our experience it is beneficial to have only one handler, and to use this handler throughout your app.

In order to achieve this, your effect objects need to follow some kind of convention, not too different from Redux actions. It can be a great shortcut to reuse existing actionCreators and actionTypes you might have built for your Redux app, for example.

One flexible pattern would be to structure your effect objects to allow calling multiple side-effects at once:

```javascript
const handler = (initialProps) => (effect) => {
    if (effect.analytics) {
        initialProps.analytics.push(effect.payload)
    }

    if (effect.dispatch) {
        initialProps.store.dispatch(effect.payload)
    }

    if (effect.localstorage) {
        localstorage.setItem(effect.payload.name, effect.payload.value)
    }

    // ...etc
}
```


# Pushing to Props

By now, you should have a better understanding of what Refract does:

* It allows you to observe data sources ([React](/usage/observing-react), [redux](https://github.com/fanduel-oss/refract/tree/bd75a6f754d175fcd418ded86ea0c37d02d19729/docs/usage/observing-redux/README.md), [anything else](/usage/observing-anything))
* It allows you to push data to an effect handler (see [handling effects](/usage/handling-effects))

Refract has three built-in effect handlers, to:

* Pass additional props to the child it wraps
* Replace props
* Render components

This section focuses on adding and replacing props, and its applications. All React, Preact and Inferno packages export two effect creators: `toProps` and `asProps`. They both take an object of props.

Note that by default, props passed to `toProps` and `asProps` won't be merged with previous values: to enable this behaviour, you need to set `mergeProps` to `true` in `withEffects` config.

## Adding Props

Any value emitted by your aperture which has been wrapped with `toProps` will cause the wrapped component to re-render with the additional provided props. Let's see a very simple example where a prop `doubledValue` is computed from a prop `value`:

```javascript
import React from 'react'
import { withEffects, toProps } from 'refract-rxjs'
import { map } from 'rxjs/operators'

const DoubleValue = ({ value, doubledValue }) => (
    <div>Two times {value} is {doubledValue}</button>
)

const aperture = (component, { initialCount }) => {
    component.observe('value').pipe(map(value => toProps({
        doubledValue: 2 * value
    })))
}

export default withEffects(aperture)(DoubleValue)
```

## Replacing Props

`asProps` is used exactly like `toProps`, except that the provided props will be the only ones passed to the child component.

It allows you to fully control what props are passed through, and can result in performance benefits by controlling exactly when a component re-renders.

Essentially, `toProps` and `asProps` allow you to inject data into components, by using existing props or external data sources (sideways data loading).

## Stateful Apertures

With the ability to set component props and to listen to events (with `pushEvent` and `component.fromEvent(name)`), comes the ability to handle state: events are the source of truth, and state is a projection of these events.

The example below is a simple counter example: each time a button is clicked, the count is incremented. We use a reducer to persist state between events, and pass it as props. It will sound familiar if you've used Redux: we go from events to state to props, the same way Redux (with `connect`) goes from actions to state to props (see [Replacing react-redux connect HoC](https://github.com/fanduel-oss/refract/tree/bd75a6f754d175fcd418ded86ea0c37d02d19729/docs/recipes/replacing-connect.md]) recipe). Refract can be used to bind together state from multiple sources.

Note the use of `component.useEvent(eventName)` which returns a tuple containing the result of `fromEvent(eventName)` and `pushEvent(eventName)` (and the use of `startWith` to ensure the `addOne` prop is passed to the component on initial render).

```javascript
import React from 'react'
import { withEffects, toProps } from 'refract-rxjs'
import { scan, startWith, map } from 'rxjs/operators'

const Counter = ({ count, addOne }) => <button onClick={addOne}>{count}</button>

const aperture = (component, { initialCount }) => {
    const [addOneEvents$, addOne] = component.useEvent('addOne')

    return addOneEvents$.pipe(
        startWith({
            count: initialCount,
            addOne
        }),
        scan(({ count, ...props }) => ({
            ...props,
            count: count + 1
        })),
        map(toProps)
    )
}

export default withEffects(aperture)(Counter)
```


# Rendering Components

Refract has built-in effect handlers:

* To pass additional props, or replace props (see [Pushing to props](/usage/pushing-to-props))
* To render components

## Pushing Elements

Rendering components can be seen as the natural continuation of pushing props: instead of pushing props to a child component, we push elements! This effectively enables you to handle React in a fully reactive manner, from source to component.

Like with [Pushing to props](/usage/pushing-to-props), it enables you to handle state by projecting it to components. Under the hood, Refract checks if a value emitted by your aperture is a valid element (React, Preact or Inferno) and renders it if it is.

The `BaseComponent` you supply to `withEffects` can be used as a placeholder (for example a loader) if your aperture doesn't synchronously emit an element to be rendered. If no base component is supplied, `null` will be rendered initially.

Below is the same counter example, pushing elements rather than props:

```javascript
import React from 'react'
import { withEffects } from 'refract-rxjs'
import { scan, startWith, map } from 'rxjs/operators'

const Counter = ({ count, addOne }) => <button onClick={addOne}>{count}</button>

const aperture = (component, { initialCount }) => {
    const [addOneEvents$, addOne] = component.useEvent('addOne')

    return addOneEvents$.pipe(
        startWith({
            count: initialCount,
            addOne
        }),
        scan(({ count, ...props }) => ({
            ...props,
            count: count + 1
        })),
        map(Counter)
    )
}

export default withEffects(aperture)()
```


# Handling Errors

When using Refract, there are two categories of errors to be aware of: *expected* errors and *unexpected* errors. Each type should be handled differently.

## Expected Errors

Expected errors are any which you can plan for in advance.

For example, an HTTP request may fail for any number of reasons, and it's good practice to take this into account and design informative error states for any which are relevant to your app.

This type of error is often handled via internal logic within an `aperture`'s streams, and sometimes via the main `handler`. This means that all expected functionality - including common error states - is taken care of within the same context.

## Unexpected Errors

Unexpected errors are any which you cannot plan for. They are usually some kind of exception which has been thrown within your logic, causing your stream to collapse.

This type of error is handled via an `errorHandler`, an optional function which can be passed into `withEffects` along with the main `handler`. This is intended to be a way for you to log unexpected errors, so that you can investigate and fix any issues which emerge when your app is being used in the real world.

An `errorHandler` has an identical function signature to a `handler`, but with an `error` instead of an `effect` passed in as the second argument:

```javascript
const errorHandler = initialProps => error => {
    /* handle error here */
}
```

## Recovering from unexpected errors

If an unexpected error occurs, it will cause your `aperture` function to no longer work and emit effects! Stream libraries have ways to catch or ignore those errors so they don't propagate and cause entire streams to terminate!

* For RxJS, you can look at [this guide](https://alligator.io/rxjs/simple-error-handling/) and [that guide](https://xgrommx.github.io/rx-book/content/getting_started_with_rxjs/creating_and_querying_observable_sequences/error_handling.html). These guides are not up to date so make sure you look up operators in the [RxJS documentation](http://reactivex.io/rxjs).
* With xstream, [use the `replaceError` operator](https://github.com/staltz/xstream#-replaceerrorreplace)
* With most, [use the `recoverWith` operator](https://github.com/cujojs/most/blob/master/docs/api.md#handling-errors)


# Testing

Refract's API has been designed so that each facet (`aperture`, `handler`, `errorHandler`) is pure, which means they can be tested in isolation.

How you test the internals of your aperture depends on which streaming library you choose, as they all offer different testing approaches. We would like to compile a list of useful links on testing for each of the streaming libraries integrated with Refract, so if you encounter any please either open a PR or get in touch via [our Discord channel](https://discord.gg/fqk86GH)!


# Recipes

* [Dependency Injection](/recipes/dependency-injection)
* [Creating An API Dependency](/recipes/creating-an-api-dependency)
* [Handling State](/recipes/handling-state)
* [Replacing Redux Connect](/recipes/replacing-connect)


# Dependency Injection

We recommend using React's new context API for dependency injection, because it is perfect for passing information through to any arbitrary child within your app.

However, it needs a little work for it to play nicely with higher-order components.

## Setting up React Context

Consider the following example, using vanilla React context:

```javascript
import { createContext } from 'react'

export default createContext()
```

```javascript
import { Provider } from 'redux'
import { withEffects } from 'refract-rxjs'

import RefractContext from './refractContext'
import configureStore from './configureStore'
import App from './components/App'

const store = configureStore()

ReactDOM.render(
    <Provider store={store}>
        <RefractContext.Provider value={{ store }}>
            <App />
        </RefractContext.Provider>
    </Provider>,
    document.getElementById('root')
)
```

## Passing context to `withEffects`

With React version 16.6.0 and above, you can pass your React context to `withEffects`. For more information about it, you can look at [`withEffects` API](/api/witheffects) and [React `class.contextType`](https://reactjs.org/docs/context.html#classcontexttype).

```javascript
import { withEffects } from 'refract-rxjs'

const MyComponent = props => <Foo {...props} />

export default withEffects(aperture, {
    handler,
    errorHandler,
    Context
})(MyComponent)
```

`handler`, `errorHandler` and `aperture` will then be called with two arguments:

* `initialProps`: the component props when your component is instantiated
* `initialContext`: the value of `Context` when your component is instantiated

## Passing context to props

If you are not using React 16.6.0 and above, you can fallback to passing your context as props and it will be available via `initialProps`:

```javascript
import { withEffects } from 'refract-rxjs'

const MyComponent = props => <Foo {...props} />

export default withEffects(aperture, { handler })(MyComponent)
```

```javascript
import MyComponent from './MyComponent' // includes effects, but no context
import RefractContext from './refractContext'

const MyView = props => (
    <RefractContext.Consumer>
        {dependencies => <MyComponent {...dependencies} {...props} />}
    </RefractContext.Consumer>
)
```

This code successfully puts dependencies into context and pulls them out again where needed, but it's not a particularly nice pattern. It's a pain to have to import the context and the component separately, and manually pass the dependencies through.

Thankfully, there's a solution for this!

## Using Context With `react-zap`

We recommend using another tiny library, [`react-zap`](https://github.com/troch/react-zap), which lets you consume React context directly via higher-order components.

At first glance, it might seem obvious to do this:

```javascript
import { withEffects } from 'refract-rxjs'
import { contextToProps } from 'react-zap'

import RefractContext from './refractContext'

const MyComponent = props => <Foo {...props} />

export default contextToProps(RefractContext.Consumer)(
    withEffects(aperture, { handler })(MyComponent)
)
```

```javascript
import MyComponent from './MyComponent' // includes effects AND context

const MyView = props => <MyComponent {...props} />
```

Which is definitely a lot nicer!

But we can do better - instead of importing and connecting our Refract context every time we use `withEffects`, we can enhance the default `withEffects` HoC by wrapping it with our context once in a `sideEffects.js` file:

```javascript
import { createContext } from 'react'
import { withEffects, compose } from 'refract-rxjs'
import { contextToProps } from 'react-zap'

const RefractContext = createContext()

const enhancedWithEffects = (aperture, { handler, errorHandler }) => BaseComponent =>
    compose(
        contextToProps(RefractContext.Consumer),
        withEffects(aperture, { handler, errorHandler })
    )(BaseComponent)

export {
    RefractProvider: RefractContext.Provider
    withEffects: enhancedWithEffects
}
```

We would now import this enhanced version instead of the plain one whenever creating a component with side-effects:

```javascript
import { withEffects } from './sideEffects'

const MyComponent = props => <Foo {...props} />

export default withEffects(aperture, { handler })(MyComponent) // now includes dependencies!
```


# Creating An API Dependency

The recommended approach to injecting dependencies into your apertures and handlers has been explored elsewhere - in the [usage section](/usage/injecting-dependencies) and in a [dependency injection](/recipes/dependency-injection) recipe - but an important question has not been covered: what does a dependency look like?

While each app likely has obvious dependencies which would be useful inside Refract - such as your router or your Redux store - there are other dependencies which would benefit from the same approach.

This recipe explores one of the typical dependencies you might find yourself building: an API dependency.

## Life Without an API Dependency

If we build an app without a centralised API dependency, we will eventually encounter a number of problems.

### Repetition

Take a typical API request using fetch as an example. The request itself might look like this:

```javascript
fetch(`https://api.github.com/users/${username}`)
    .then(response => response.json())
    .catch(error => console.error(error))
```

When using fetch inside an aperture, there's actually a little extra boilerplate needed, and even worse it makes our aperture impure:

```javascript
const aperture = component =>
    component.observe('username').pipe(
        mergeMap(username =>
            fromPromise(
                fetch(`https://api.github.com/users/${username}`)
                    .then(response => response.json())
                    .catch(error => ({ type: RECEIVE_ERROR, error }))
            )
        )
    )
```

The error catching logic is also problematic. If we take the approach shown above, we need to handle the different types of data being emitted inside one stream.

Alternatively, we could introduce even more boilerplate and handle errors directly in the stream:

```javascript
const aperture = component =>
    component
        .observe('username')
        .pipe(
            mergeMap(username =>
                fromPromise(
                    fetch(`https://api.github.com/users/${username}`).then(
                        response => response.json()
                    )
                )
            ),
            catchError(error => of({ type: RECEIVE_ERROR, error }))
        )
```

Neither feels like a clean solution - it's still a lot of overhead for a simple API request.

### Flexibility

This approach makes the code harder to change. What if we want to migrate to a new version of the API, add an extra header to all requests, or add some common data transformation to a specific endpoint?

To make those changes, we would have to trawl through our app, find every API request, and consider the context of each request to make sure we're refactoring correctly.

### Testability

Calling fetch inside our aperture makes our aperture impure, and we would have to use something like Jest's module mocking system to test it.

### Request Cancellation

Depending on how we use the imperative fetch requests, we might not be able to cancel any in-flight requests.

## The Solution

So what's the alternative?

The end goal is a dependency which can be added to our app much like a Redux store: a JavaScript object containing methods which we can call, isolating the impure code and wrapping it into a format which we can easily mock in tests.

```javascript
const apiDependency = {
    getUser: username =>
        fromPromise(
            fetch(`https://api.github.com/users/${username}`)
                .then(response => response.json())
                .catch(error => ({ error }))
        )
}

ReactDOM.render(<App api={apiDependency} />)
```

This dependency could then be exposed to Refract, allowing it to be called inside the apertures like so:

```javascript
const aperture = (component, { api }) =>
    component
        .observe('username')
        .pipe(mergeMap(username => api.getUser(username)))
```

This is a much cleaner separation of concerns, allowing us to declaratively call our API endpoints - without caring about the implementation details, and without unnecessary repetition.

When refactoring the API, all the related code is in one place, and we no longer have to consider the context in which it is called. When testing, we can easily create a mock dependency, and our apertures remain pure.

## Considerations

### Using Your API Dependency Outside Refract

If you handle all of your app's side-effects via Refract, you have the opportunity to build your API dependency with this in mind.

By using primitives from your streaming library as building blocks, you can simplify features such as request cancellation, retry on error, or complex data transformations. Encapsulating your API into a single dependency lets you consider it in isolation, and makes your code clearer and more consistent.

However, using Refract that extensively might not be your goal - or you might need to migrate an existing app over time. In those cases, a centralised dependency would still provide some of those benefits, and could be a natural first step towards migrating.

The main difference in approach is that you would likely return raw promises instead of streams, so that they can be easily used outside Refract. You would still gain from the testability and consistency, and make it easier to refactor in future.

### Runtime Configuration

Another significant advantage to this approach is that it can simplify runtime API configuration. For example, if you need to pass some data along with every request, you can achieve this by instantiating your api dependency inside a callback function:

```javascript
const createApiDependency = ({ apiUrl, client }) => {
    const apiHeaders = {
        Authorization: client.authorization
    }

    const request = axios.create({
        baseUrl: apiUrl,
        headers: apiHeaders
    })

    return {
        getUser: username =>
            fromPromise(
                request(`https://api.github.com/users/${username}`)
                    .then(response => response.json())
                    .catch(error => ({ error }))
            )
    }
}
```

More complex configuration is also made possible via this separation of the API into its own isolated module.


# Handling state

State in React is a never-ending story: you can use Redux, vanilla local state, higher-order components built on top of local state, use the new context API...

We believe state strongly coupled to components is best colocated: it is easier to reason about, easier to maintain and enables you to cleanly isolate sections of an application. Refract makes it possible to handle local state reactively, and it might even challenge some of your assumptions.

## Source of truth

Redux popularised state as a source of truth: in a Redux app, state is indeed the source of truth of your view, because a hard separation is enforced. However, actions (which are like events) are the source of truth of your reducers and therefore state.

In any application, events are the source of truth! Any application projects them (reduces them if you prefer!) to state. And state can be represented in different ways: an object, or a React element.

A counter for instance will have `'click'` events resulting in a value being incremented (`{count: 1}`) and rendered `<span>{count}</span>`: from event, to representation.

## Stateful apertures

Refract can observe "events" (see [Observing React](/usage/observing-react)) and has built-in effects: to [map and replace props](/usage/pushing-to-props) and to [render components](/usage/rendering-components); it allows you to handle the different transformation steps, from events to presentation, in one place.

The example below is a very basic example of a toggle. We have a `Toggle` component which can reveal content (`children`).

```javascript
import React from 'react'

export default function Toggle({ isExpanded, toggle, children }) {
    return (
        <div>
            <button onClick={toggle}>{isExpanded ? 'Hide' : 'Reveal'}</button>

            {isExpanded ? children : null}
        </div>
    )
}
```

We wrap this component with Refract, so we can provide the `toggle` callback, and map state to props.

```javascript
import React from 'react'
import { withEffects, toProps } from 'refract-rxjs'
import { scan, startWith, map } from 'rxjs/operators'
import Toggle from './Toggle'

const aperture = component => {
    const [toggleEvents$, toggle] = component.useEvent('toggle')

    return toggleEvents$.pipe(
        startWith({
            toggle,
            isExpanded: false
        }),
        scan(props => ({
            ...props,
            isExpanded: !props.isExpanded
        })),
        map(toProps)
    )
}

const ToggleWithState = withEffects(aperture)(Toggle)

export default ToggleWithState
```

## Using context

When handling local state, it can be cumbersome to have to pass props through several layers of components (this is known as "prop drilling"). React's new context API can help with it, and you can leverage it with Refract by using rendering effects.

The example below puts a counter state in context. In the aperture, we create a context object from `'count'` events and combine them with the values of `children` received to set the value of a context provider.

```javascript
import React from 'react'
import { withEffects } from 'refract-rxjs'
import { combineLatest } from 'rxjs'
import { scan, startWith, map } from 'rxjs/operators'

const { Provider, Consumer: CounterStateConsumer } = React.createContext({})

const aperture = (component, initialProps) => {
    const children$ = component.observe('children')

    const [countEvents$, countUp] = component.useEvent('count')
    const context$ = countEvents$.pipe(
        startWith({
            countUp,
            count: initialProps.initialCount
        }),
        scan(context => ({
            ...context,
            count: context.count + 1
        }))
    )

    return combineLatest(context$, children$).pipe(
        map(([context, children]) => (
            <Provider value={context}>{children}</Provider>
        ))
    )
}

const CounterStateProvider = withEffects(aperture)()

export { CounterStateProvider, CounterStateConsumer }
```


# Replacing Redux Connect

It is possible to [handle local state](/recipes/handling-state) in Refract, and Refract enables you to [observe any data source](/usage/observing-anything): as a result, we can easily and reactively map any data source to props with Refract.

This recipe will show you how you can replace `connect` from the `react-redux` package using Refract. The syntax is not as compact as `connect`, but it has several benefits:

* You have full control over when children are rendered: the required selectors don't have to be re-computed every single time or loaded upfront (you can lazy load selectors)
* You can leverage Refract to handle other effects (network requests, analytics, etc.)
* You can mix it with other data sources (props, other external sources)

We recommend you look at [Installation](/usage/installation) and [Observing Redux](/usage/observing-redux) if you haven't already.

`connect` takes three arguments (`mapStateToProps`, `mapDispatchToProps`, `mergeProps`) and we are going to go through how to replace each of them.

## Mapping state to props

Given that we have a Redux store available in our props (see [Injecting Dependencies](/usage/injecting-dependencies)) and that we have added the Refract store enhancer, we can observe selectors and map their output to props:

```javascript
import { combineLatest } from 'rxjs'
import { map } from 'rxjs/operators'
import { withEffects, toProps } from 'refract-rxjs'
import { getUser, getPosts } from './mySelectors'

const aperture = (component, initialProps) => {
    const { store } = initialProps

    const user$ = store.observe(getUser)
    const posts$ = store.observe(getPosts)

    return combineLatest(users$, posts$).pipe(
        map(([user, posts]) => ({
            user,
            posts
        })),
        map(toProps)
    )
}

const ContainerComponent = withEffects(aperture)(BaseComponent)
```

Let's look at the example above step by step:

* We create two streams (`user$`, `posts$`) from two selectors (`getUser`, `getPosts`)
* We combine these two streams into another stream where:
  * We create an object containing users and posts (`{ user, posts }`)
  * We pass each object to our component's props (with `toProps`)

The result is the same as `connect`: `users` and `posts` will be added to our component's props. The Refract way is more verbose in some cases, but there are a few things which can be leveraged from reactive programming:

* Selective updates: you can choose when to listen to selectors
  * We might only be interested in getting the first `user` value: `const user$ = store.observe(getUser).pipe(take(1))`
  * We might want to only get posts per user

```javascript
    const posts$ = store.observe(getUser).pipe(
        map(user => user ? user.id : null),
        distinctUntilChanged(),
        switchMap(userId => userId ? store.observe(getPosts(userId)) : empty())
    )
```

* Due to the point above, you no longer need to use thunks inside `mapStateToProps` and you no longer to use memoized selectors (using [reselect](https://github.com/reduxjs/reselect)): dependencies of a selector can be expressed using streams.

## Mapping action creators to props

Replacing `mapDispatchToProps` can be done in different ways. A first way would be to do it exactly like `connect` by binding `dispatch` to each action creator and pushing them to props using `toProps`.

Instead, we are going to look at a different way: dispatching is imperative and can be seen as a side-effect, so we are going to treat it as such and move its use to an effect handler. We push event callbacks to our component (using `pushEvent`), observe them, pass their values to their respective action creators and send the whole lot to be dispatched.

```javascript
import { withEffects, toProps } from 'refract-rxjs'
import { of, merge } from 'rxjs'
import { map } from 'rxjs/operators'
import { createAddPostAction, createRemovePostAction } from './actions'

const handler = initialProps => effect => {
    const { store } = initialProps

    if (effect.type === 'DISPATCH') {
        store.dispatch(effect.payload)
    }
}

const toDispatch = action => ({
    type: 'DISPATCH',
    payload: action
})

const aperture = component => {
    const [ addPostEvents$, addPost] = component.pushEvent('addPost')
    const [ removePostEvents$, removePost] = component.pushEvent('removePost')

    return merge(
        of({
            addPost,
            removePost
        }).pipe(map(toProps)),

        merge(
            addPostEvents$.pipe(map(createAddPostAction)),
            removePostEvents$.pipe(map(createRemovePostAction))
        ).pipe(map(toDispatch))
    })
}

const ContainerComponent = withEffects(aperture, { handler })(BaseComponent)
```

Again, it is a more verbose approach than `mapDispatchToProps`. But by separating action creation from dispatching logic, it enables you to hook other side-effects that you could otherwise find in a Redux middleware (like analytics events).

## Merging props

The third less-known argument of `connect` is `mergeProps`: it takes the component's props, the outputs of `mapStateToProps` and `mapDispatchToProps`, and merges them together (by default). It would typically be used for preventing some component's props to be passed down, or to perform extra computations. This is no longer needed, since you can map or replace props in Refract: see [Pusing to props](/usage/pushing-to-props).


# Examples

## Examples

|                                                    | callbag                                                                                                                                    | most                                                                                                                                    | RxJS                                                                                                                                    | xstream                                                                                                                                    |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Basic                                              |                                                                                                                                            |                                                                                                                                         |                                                                                                                                         |                                                                                                                                            |
| [**Debounced Fetch**](/examples/debounced-fetch)   | [`code`](https://git.io/fAZPF) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/debounced-fetch/callbag)  | [`code`](https://git.io/fAZX8) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/debounced-fetch/most)  | [`code`](https://git.io/fAZX9) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/debounced-fetch/rxjs)  | [`code`](https://git.io/fAZXH) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/debounced-fetch/xstream)  |
| [**Counter**](/examples/counter)                   | [`code`](https://git.io/fAZ1q) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/counter/callbag)          | [`code`](https://git.io/fAZ1m) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/counter/most)          | [`code`](https://git.io/fAZ1Y) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/counter/rxjs)          | [`code`](https://git.io/fAZ1O) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/counter/xstream)          |
| [**Field Validation**](/examples/field-validation) | [`code`](https://git.io/fAZ14) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/field-validation/callbag) | [`code`](https://git.io/fAZ1B) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/field-validation/most) | [`code`](https://git.io/fAZ1R) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/field-validation/rxjs) | [`code`](https://git.io/fAZ10) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/field-validation/xstream) |
| [**Redux Fetch**](/examples/redux-fetch)           | [`code`](https://git.io/fAZ1d) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/redux-fetch/callbag)      | [`code`](https://git.io/fAZ1F) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/redux-fetch/most)      | [`code`](https://git.io/fAZ1b) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/redux-fetch/rxjs)      | [`code`](https://git.io/fAZ1A) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/redux-fetch/xstream)      |
| [**Typeahead**](/examples/typeahead)               | [`code`](https://git.io/fAZ1E) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/typeahead/callbag)        | [`code`](https://git.io/fAZ1W) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/typeahead/most)        | [`code`](https://git.io/fAZ1n) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/typeahead/rxjs)        | [`code`](https://git.io/fAZ1G) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/typeahead/xstream)        |
|                                                    |                                                                                                                                            |                                                                                                                                         |                                                                                                                                         |                                                                                                                                            |
| Advanced                                           |                                                                                                                                            |                                                                                                                                         |                                                                                                                                         |                                                                                                                                            |
| [**Routing**](/examples/routing)                   | [`code`](https://git.io/fAZ1Q) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/routing/callbag)          | [`code`](https://git.io/fAZ1y) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/routing/most)          | [`code`](https://git.io/fAZ1P) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/routing/rxjs)          | [`code`](https://git.io/fAZ1K) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/routing/xstream)          |
| [**Visit Time**](/examples/visit-time)             | [`code`](https://git.io/fAZXb) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/visit-time/callbag)       | [`code`](https://git.io/fAZ1e) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/visit-time/most)       | [`code`](https://git.io/fAZ1U) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/visit-time/rxjs)       | [`code`](https://git.io/fAZ1I) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/visit-time/xstream)       |


# Debounced fetch

## Debounced Fetch

| callbag                                                                                                                                   | most                                                                                                                                   | RxJS                                                                                                                                   | xstream                                                                                                                                   |
| ----------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| [`code`](https://git.io/fAZPF) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/debounced-fetch/callbag) | [`code`](https://git.io/fAZX8) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/debounced-fetch/most) | [`code`](https://git.io/fAZX9) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/debounced-fetch/rxjs) | [`code`](https://git.io/fAZXH) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/debounced-fetch/xstream) |

This basic example renders a single text input which prompts for a GitHub username; the current `username` of this input is stored in React component state.

### Aperture

Only one source is observed:

* The `username` prop.

Every time the input's `username` changes, the new username is passed to the stream. Any blank strings are filtered from the stream, and then the usernames are debounced for one second.

After debouncing, a fetch request is made and resolved; the response of this request is output as an effect with a type of `USER_DATA_RECEIVE`.

### Handler

The Refract `handler` sets the payload of any effect with a type of `USER_DATA_RECEIVE` into state, ready to be displayed in the UI.

### Result

The end result is a debounced fetch request based on input's current value, with the results rendered to the UI.


# Counter

## Counter

| callbag                                                                                                                           | most                                                                                                                           | RxJS                                                                                                                           | xstream                                                                                                                           |
| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| [`code`](https://git.io/fAZ1q) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/counter/callbag) | [`code`](https://git.io/fAZ1m) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/counter/most) | [`code`](https://git.io/fAZ1Y) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/counter/rxjs) | [`code`](https://git.io/fAZ1O) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/counter/xstream) |

This basic example involves a `counter` which the user can toggle between `incrementing`, `decrementing`, and `paused` states. The parent component has a simple state: `{ counter: 0, direction: 'NONE' }`. The buttons in the UI alter the `direction` state.

### Aperture

Two sources are observed:

* The `setDirection` callback function.
* An interval which dispatches a new number every second.

Every time `setDirection` is called, the value it was called with is dispatched.

These two sources are then merged; the resulting stream contains a new effect every second, which contains the current direction as its `type`.

### Handler

Simply increments or decrements the state whenever an effect is dispatched with the correct effect type.

### Result

The end result is a counter which infinitely counts upwards after the user clicks `increase`, infinitely counts downwards after the user clicks `decrease`, or stays static after the user clicks `pause`.


# Field validation

## Field Validation

| callbag                                                                                                                                    | most                                                                                                                                    | RxJS                                                                                                                                    | xstream                                                                                                                                    |
| ------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| [`code`](https://git.io/fAZ14) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/field-validation/callbag) | [`code`](https://git.io/fAZ1B) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/field-validation/most) | [`code`](https://git.io/fAZ1R) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/field-validation/rxjs) | [`code`](https://git.io/fAZ10) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/field-validation/xstream) |

This basic example renders a single text input which prompts for a GitHub username; the current `username` of this input is stored in React component state.

### Aperture

Only one source is observed:

* The `username` prop.

Every time the input's `username` changes, the new username is passed to the stream. Any blank strings are filtered from the stream, and then the usernames are debounced for one second.

After debouncing, a fetch request is made and resolved. If a user is found, an effect with type `USER_FOUND` is output; if no user is found, an effect with type `USERNAME_AVAILABLE` is output.

### Handler

The Refract `handler` toggles the `available` state appropriately depending on the effect's type.

### Result

The end result is an input field with asynchronous validation handled as a side-effect.


# Redux fetch

## Redux Fetch

| callbag                                                                                                                               | most                                                                                                                               | RxJS                                                                                                                               | xstream                                                                                                                               |
| ------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| [`code`](https://git.io/fAZ1d) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/redux-fetch/callbag) | [`code`](https://git.io/fAZ1F) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/redux-fetch/most) | [`code`](https://git.io/fAZ1b) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/redux-fetch/rxjs) | [`code`](https://git.io/fAZ1A) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/redux-fetch/xstream) |

This basic example renders a single text input which prompts for a GitHub username. When the user submits the form (either by clicking the button or pressing return), it dispatches a plain action to Redux.

### Aperture

Inside the Refract `aperture`, two observables are observed: the `USER_REQUEST` action, and the `getUsers` selector. Every time an action with the type `USER_REQUEST` is dispatched to the store, it is passed to the stream; every time the `users` object in the redux store changes, it is also passed to the stream.

These two streams are combined into one `combined$` - each time anything is sent to either stream, this new stream emits a new tuple containing the most recent value from *both* source streams.

This combined stream is piped through various methods in two separate control flows: requests for users whose data is not yet in redux are mapped to a fetch request, with error handling built in; requests for users whose data *is* already in the store are mapped to a `selectUser` action.

### Handler

The Refract `handler` inspects the type of each effect, and causes different effects for different action types. If the effect is an error, it logs the effect; if the effect is either a `USER_RECEIVE` or a `USER_SELECT` effect, it is dispatched to the store.

### Result

The end result is a form with some complex conditional, asynchronous logic built in an easily maintainable way.


# Routing

## Routing

| callbag                                                                                                                           | most                                                                                                                           | RxJS                                                                                                                           | xstream                                                                                                                           |
| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| [`code`](https://git.io/fAZ1Q) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/routing/callbag) | [`code`](https://git.io/fAZ1y) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/routing/most) | [`code`](https://git.io/fAZ1P) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/routing/rxjs) | [`code`](https://git.io/fAZ1K) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/routing/xstream) |

In this example, a set of tabs are rendered to the screen, with the currently active tab stored in React state.

### Aperture

Two sources are observed in this example:

* The `setActiveTab` callback function.
* The `window.popstate` event.

In addition, a single event is fired when the `aperture` initiates, which sets the initial state to `initialProps.activeTab`.

All three are simply mapped to objects with the desired structure, and merged into a single stream.

### Handler

If the effect's type is `NAVIGATION`, the `handler` calculates the new browser url, and pushes it to `window.history`.

If the effect's type is `STATE`, it calls `setActiveTab` with the new state.

### Result

The end result is a set of tabs whose state is pushed to the browser url as a side-effect.


# Typeahead

## Typeahead

| callbag                                                                                                                             | most                                                                                                                             | RxJS                                                                                                                             | xstream                                                                                                                             |
| ----------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| [`code`](https://git.io/fAZ1E) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/typeahead/callbag) | [`code`](https://git.io/fAZ1W) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/typeahead/most) | [`code`](https://git.io/fAZ1n) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/typeahead/rxjs) | [`code`](https://git.io/fAZ1G) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/typeahead/xstream) |

In this example, a GitHub username searchbox is rendered to the screen. The searchbox includes a typeahead, which fetches username suggestions based on what the user has typed so far.

When a user clicks on a suggestion, or presses the return key while the textbox (or a suggestion) is focused, the selected GitHub account's data is fetched, and rendered to the screen.

### Aperture

Two sources are observed in this example:

* The `search` prop.
* The `selection` prop.

The `search` prop is used as the source for two separate streams.

First, a stream of suggestions. Each time the `search` prop changes, if its value is truthy, it is debounced and sent through a pipeline which includes an asynchronous fetch request, and some data manipulation.

In a separate stream of logic, each time the `search` prop changes, if its value is an empty string, it is mapped to another `setState` effect which resets the `suggestions` state to an empty array.

Finally, a stream of users. Each time the `selection` prop changes, it is sent through a similar logic pipeline to the first stream, which results in the `user` state being updated.

These three streams are merged into one, and returned as the output of the `aperture`.

Note that all three streams used a `toState` "effectCreator" function at the end - this is a helper function similar to a redux `actionCreator`.

### Handler

If the effect's type is `SET_STATE`, the `handler` passes the effect's payload into `initialProps.setState`.

### Result

The end result is an intelligent user interface which exposes search suggestions and fetches user data as a side-effect.


# Visit time

## Visit time

| callbag                                                                                                                              | most                                                                                                                              | RxJS                                                                                                                              | xstream                                                                                                                              |
| ------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| [`code`](https://git.io/fAZXb) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/visit-time/callbag) | [`code`](https://git.io/fAZ1e) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/visit-time/most) | [`code`](https://git.io/fAZ1U) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/visit-time/rxjs) | [`code`](https://git.io/fAZ1I) [`live`](https://codesandbox.io/s/github/fanduel-oss/refract/tree/master/examples/visit-time/xstream) |

This examples renders a stopwatch counting the time a user spends on a page while being online.

### Aperture

Two sources observed:

* The visibility status of the page (See [page visibility API](https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API))
* The online status of the navigator (See [online and offline events](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/Online_and_offline_events))

Every time the page becomes visible and online, the stopwatch resumes. If the page becomes either offline or hidden, the stopwatch pauses.

### Handler

The Refract `handler` handles `pause`, `resume` and `tick` effects to track the total time spent on the page and set it in state. It handles `Date.now()` impure calls.

### Result

The end result is a stopwatch counting the number of milliseconds spent on the page when visible and online. To play with it you can:

* switch between tabs, and you'll notice the counter hasn't moved while the example tab was hidden
* toggle your navigator online status (can be done via devtools)


# API

## React, Inferno and Preact Packages

* [compose](/api/compose)
* [withEffects](/api/witheffects)
* [toProps, asProps](/api/props)
* [useRefract](/api/userefract)

## Redux Packages

* [refractEnhancer](/api/refractenhancer)


# compose

Used for composing functions from right to left, it is a very useful utility for composing higher-order components in React, Inferno or Preact.

## Packages

`compose` is provided by our React, Inferno or Preact packages - `refract-*`, `refract-inferno-*`, `refract-preact-*`.

## Signature

`compose` will compose multiple function to create a function which takes a single argument.

```javascript
compose = (...functions) => arg => result
```

Using `compose` with three functions `f`, `g` and `h` is the equivalent of `arg => f(g(h(arg)))`

## Example

```javascript
import { connect } from 'react-redux'
import { withEffects, compose } from 'refract-rxjs'

const WrappedComponent = compose(
    connect(mapStateToProps, mapDispatchToProps),
    withEffects(aperture)
)(BaseComponent)
```


# withEffects

Used to enhance a plain component, wrapping it in a WithEffects component which handles side-effects internally. It is a curried higher-order component.

## Packages

`withEffects` is provided by our React, Inferno or Preact packages - `refract-*`, `refract-inferno-*`, `refract-preact-*`.

## Signature

```javascript
withEffects = (
    aperture,
    config: { handler?, errorHandler?, Context?, mergeProps?, decorateProps? }
) => BaseComponent => {
    return WrappedComponent
}
```

## Arguments

1. `aperture` *(function)*: a function which observes data sources within your app, passes this data through any necessary logic flows, and outputs a stream of `effect` values in response.

   Signature: `(component, initialProps, initialContext?) => { return effectStream }`.

   * The `component` is an object which lets you observe your React, Inferno or Preact component: see [Observing React](/usage/observing-react)
   * The `initialProps` are all props passed into the `WrappedComponent`.
   * The `initialContext` is the initial context value of the provided `Context` (see above, React >= 16.6.0 only)
   * Within the body of the function, you observe the event source you choose, pipe the events through your stream library of choice, and return a single stream of effects.
2. a `config` object optionally containing the following:
   1. `handler` *(function)*: an *optional* function which causes side-effects in response to `effect` values.

      Signature: `(initialProps, initialContext?) => (effect) => { /* handle effect here */ }`

      * The `initialProps` are all props passed into the `WrappedComponent`.
      * The `initialContext` is the initial context value of the provided `Context` (see below, React >= 16.6.0 only)
      * The `effect` is each value emitted by your `aperture`.
      * Within the body of the function, you cause any side-effect you wish.
   2. `errorHandler` *(function)*: an *optional* function for catching any unexpected errors thrown within your `aperture`. Typically used for logging errors.

      Signature: `(initialProps, initialContext?) => (error) => { /* handle error here */ }`

      * The `initialProps` are all props passed into the `WrappedComponent`.
      * The `initialContext` is the initial context value of the provided `Context` (see below, React >= 16.6.0 only)
      * The `error` is each value emitted by your `aperture`.
      * Within the body of the function, you cause any side-effect you wish.
   3. `Context` *(ReactContext)*: a React Context object. Its initial value will be passed to `handler`, `errorHandler` and `aperture` (React 16.6.0 and above only).
   4. `mergeProps`: whether or not props passed with `toProps` or `asProps` should be merged together.
   5. `decorateProps`: whether or not props which are functions should be decorated, so their arguments can be observed (default to `true`).
3. `BaseComponent` *(React component)*: any react component.

## Returns

`WrappedComponent` *(React component)*: a new component which contains your side-effect logic, and which will render your component as per usual.

## Example

```javascript
import { withEffects } from 'refract-rxjs'

const BaseComponent = ({ username, onChange }) => (
    <input value={username} onChange={onChange} />
)

const aperture = component => {
    return component.observe('username').pipe(
        debounce(2000),
        map(username => ({
            type: 'localstorage',
            name: 'username',
            value: username
        }))
    )
}

const handler = initialProps => effect => {
    switch (effect.type) {
        case 'localstorage':
            localstorage.setItem(effect.name, effect.value)
            return
    }
}

const WrappedComponent = withEffects(aperture, { handler })(BaseComponent)
```

## Tips

* Take a look at our recipe for [dependency injection](/recipes/dependency-injection) into your Refract components.
* `withEffects` is curried so that you can re-use a bound `handler` (and `errorHandler`) with multiple different `apertures`.


# toProps, asProps

## Packages

`toProps` and `asProps` are provided by our React, Inferno or Preact packages - `refract-*`, `refract-inferno-*`, `refract-preact-*`.

Note that by default, props passed to `toProps` and `asProps` won't be merged with previous values: to enable this behaviour, you need to set `mergeProps` to `true` in `withEffects` config.

## Arguments

Both `toProps` and `asProps` take an object of props.

## Returns

Similarly to a Redux action creator, they return an object containing `type` and `payload` attributes, so it can be recognised by Refract.

```javascript
export const toProps = props => ({
    type: PROPS_EFFECT,
    payload: {
        replace: false,
        props
    }
})

export const asProps = props => ({
    type: PROPS_EFFECT,
    payload: {
        replace: true,
        props
    }
})
```


# useRefract

Used to create a custom hook.

## Packages

`useRefract` is provided by our React packages - `refract-*`. It is only available for versions of React supporting hooks (React 16.7.0-alpha.0 and above).

## Signature

```javascript
const useRefract = useRefract(aperture, data, {
    handler,
    errorHandler
})
```

## Arguments

1. `aperture` *(function)*: a function which observes data sources within your app, passes this data through any necessary logic flows, and outputs a stream of `effect` values in response.

   Signature: `(component, initialData) => { return effectStream }`.

   * The `initialData` passed to the hook (second argument).
   * The `component` is an object which lets you observe: see [Observing React](/usage/observing-react). The `observe` method allows you to observe `data` passed to your hook.
   * Within the body of the function, you observe the event source you choose, pipe the events through your stream library of choice, and return a single stream of effects.
2. `data` *(object)*: an object of data (state, props, context) passed to your hook.
3. `handler` *(function)*: a *optional* function which causes side-effects in response to `effect` values.

   Signature: `(initialData) => (effect) => { /* handle effect here */ }`

   * The `initialData` passed to the hook (second argument).
   * The `effect` is each value emitted by your `aperture`.
   * Within the body of the function, you cause any side-effect you wish.
4. `errorHandler` *(function)*: an *optional* function for catching any unexpected errors thrown within your `aperture`. Typically used for logging errors.

   Signature: `(initialData) => (error) => { /* handle error here */ }`

   * The `initialData` passed to the hook (second argument).
   * The `error` is each value emitted by your `aperture`.
   * Within the body of the function, you cause any side-effect you wish.

## Returns

`componentData` *(any)*: Refract hooks have a special built-in effect to push data to your component. Effects emitted by your aperture and wrapped with `toRender` will be returned by your hook.

```javascript
import { toRender } from 'refract-rxjs'
```

## Example

```javascript
import { useRefract } from 'refract-rxjs'

const handler = initialData => effect => {
    switch (effect.type) {
        case 'localstorage':
            localStorage.setItem(effect.name, effect.value)
            return
    }
}

const aperture = (component, initialData) => {
    return component.observe('username').pipe(
        debounceTime(2000),
        map(username => ({
            type: 'localstorage',
            name: 'username',
            value: username
        }))
    )
}

const BaseComponent = () => {
    const [ username, setUsername ] = useState()

    useRefract(aperture, { username }, { handler })

    return <input value={username} onChange={evt => setUsername(evt.target.value)} />
)
```

## Tips

Take a look at our recipe for [dependency injection](/recipes/dependency-injection) into your Refract components.


# refractEnhancer (Redux)

Used to enhance a Redux store, adding observable functionality which can be used inside Refract.

## Packages

`refractEnhancer` is provided by our Redux packages - `refract-redux-callbag`, `refract-redux-most`, `refract-redux-rxjs`, and `refract-redux-xstream`.

## Signature

```javascript
refractEnhancer = (options?) => {
    return StoreCreator
}
```

## Arguments

1. `options` *(object)*: an object which configures the Refract store enhancer.

   Two options are currently available for the `refractEnhancer`:

   * `eventsPrefix` *(string)*: defines an actionType prefix which marks actions which are *not* intended to be forwarded to your reducers. Refract will intercept these, preventing them from touching your state (or any downstream store enhancers), but will forward them on to any watching apertures. (default: `@@event/`)
   * `methodName` *(string)*: customises the name used for the `store.observe` method. (default: `observe`)

     Note that customising the `methodName` option with TypeScript will break the Redux `Store` interface, which is extended when you import the Refract enhancer. To use this option with TypeScript, you will need to extend the interface - for example:

     ```javascript
     import { StoreObserveFunction } from 'refract-redux-rxjs'

     declare module 'redux' {
         interface Store {
             observeWithRxjs: StoreObserveFunction
         }
     }
     ```

## Returns

`StoreCreator` *(Redux store creator)*: a function which creates a redux store. Note that you should not be calling this function directly, and instead should be passing it into Redux `createStore`.

## Example

```javascript
import { createStore } from 'redux'
import { refractEnhancer } from 'refract-redux-rxjs'
import rootReducer from './reducers'
​
export default function configureStore() {
    const store = createStore(rootReducer, null, refractEnhancer())
    ​
    return store
}
```

[Read more about configuring your Redux store here!](https://redux.js.org/recipes/configuring-your-store)


# Glossary

## Side-Effects

A `side-effect` is a general term in computer science. In the context of an app, it means any interaction with the world outside of the internal logic of your app. Typical examples of a include API requests, analytics, logging, local storage, and so on.

## Aperture

An `aperture` controls the streams of data which enter Refract.

```javascript
type Aperture<P, E, C> = (
    component: ObservableComponent,
    initialProps: P,
    initialContext: C
) => Observable<E>
```

It is a function which observes data sources within your app, passes this data through any necessary logic flows, and outputs a stream of `effect` values in response.

## Effect

An `effect` is any value, passed from an `aperture` into a `handler`. These can be any value: numbers, strings, booleans, etc - you get to decide how to structure your effects.

It's expected that for most applications, `effect`s will likely be plain JavaScript objects (or arrays of objects if you want to dispatch multiple effects simultaneously) - this works well for more complex apps.

## Handler

A `handler` causes side-effects in response to any `effect` value output by the `aperture`.

```javascript
type Handler<P, E> = (initialProps: P, initialContext: C) => (effect: E) => void
```

It is a function which imperatively calls any side-effect you wish to result from the output of your aperture. This often includes returning data to your app's flow (via `setState` or Redux `dispatch` for example), but could also include external side-effects which do not loop back into your app (such as localstorage or analytics).

## ErrorHandler

An `errorHandler` causes side-effects in response to any fatal error occurring within your `aperture`.

```javascript
type ErrorHandler<P> = (
    initialProps: P,
    initialContext: C
) => (error: any) => void
```

It is a function which calls any side-effect you wish to result from any fatal errors within your streams. In some situations, an error can occur which breaks your stream pipeline. In this case, the error is handled by your `errorHandler`. Usually, you would be expected to log this error for further investigation.


# Feedback

We appreciate feedback from the community. You can post feature requests and bug reports via GitHub issues, or join the discussion [in our Discord channel](https://discord.gg/fqk86GH).


