# Composing Custom Subscriptions

## Writing a Subscription

### The Basics

The most basic subscription looks like this:

```javascript
const myCoolSubscription = (dispatch, ...yourArgsHere) => {
  // Do your stuff here
  
  return () => {
    // Clean your stuff up here
  };
};
```

If this doesn't do everything you want, we can definitely add some arguments:

```javascript
const myCoolSubscription = (dispatch, a, b) => {
  // Do your stuff here with a and b
  
  return () => {
    // Clean your stuff up here
  };
};
```

This is all well and good, but there is a hitch - your parameters need to be consistent. If you are dynamically creating an object, or pass in different values, your subscription will be reset. One thing about subscriptions is they introduce one-way communication, being that you set a few defaults to initialize the subscription, but all other communication is from the subscription back into the application.

### Smart Subscription Parameters

One very important detail to remember with subscriptions is a change in parameters will do a clean up of the old subscription and rebuild a new one. This means a change in value or reference. This means changing a value from `0` to `1`, `'hello'` to `'goodbye'`, or passing an inline function like `() => 'foo'`. Knowing when it's a good time to change these values to rebuild subscriptions can be hard, and knowing how to keep the same reference is equally hard. Here's an example of a bad subscription:

```javascript
const { app, effects } = require('ferp');

const tickEffect = () => ({ type: 'tick' });

const tickSubscription = (dispatch, delay) => {
  console.log('Create tick sub every', delay, 'milliseconds');
  const handle = setInterval(effects.thunk, delay, tickEffect);
  
  return () => {
    console.log('Destroy tick sub every', delay, 'milliseconds');
    clearInterval(handle);
  };
}

app({
  init: [{}, effects.none()],
  subscribe: state => [
    [tickSubscription, (Math.random() * 1000) + 1000], // Hmmmm
  ],
});
```

This is bad because the result of `(Math.random() * 1000) + 1000` will be different every time it is calculated (which will be every update), and as a result, will forcibly clean up the previous subscription and create a new subscription every application action that is ran.

If you want a consistent calculated value, you should put it in state. To do this with the above example, it would look like:

```javascript
const { app, effects } = require('ferp');


const tickSubscription = (dispatch, delay) => {
  console.log('Create tick sub every', delay, 'milliseconds');
  const handle = setInterval(effects.thunk, delay, tickEffect);
  
  return () => {
    console.log('Destroy tick sub every', delay, 'milliseconds');
    clearInterval(handle);
  };
}

app({
  init: [{ delay: (Math.random() * 1000) + 1000 }, effects.none()],
  subscribe: state => [
    [tickSubscription, state.delay], // That's better!
  ],
});
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ferp.mrbarry.com/understanding-subscriptions-in-ferp/creating-a-subscription.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
