# What is a Ferp Action?

## Actions

Actions are the only way to initiate new state changes and side-effects in Ferp. State changes must be complete and immutable, and side effects must always be declared, even if there are no side-effects. Actions are always pure functions that return `[state, sideEffect]`, and pure meaning it does not use any data not immediately accessible to the action. On the contrary, an invalid action would use things like `Math.random()` or `Date.now()`, which are external to the action function.

## Types of Actions

### Naked Action

Plain, or naked, actions are actions that need no parameters. For instance, a naked action could be something that only updates a single state property by incrementing it by 1. Let's see what that looks like:

```javascript
import { effects } from 'ferp';

const IncrementCounterByOne = (state) => [
  { ...state, counter: state.counter + 1 },
  effects.none(),
];
```

Depending on the shape of your state, you may find naked actions to be very fitting.

There are two ways to call an action, and here they are:

```javascript
import { app, effects } from 'ferp';

const IncrementCounterByOne = (state) => [
  { ...state, counter: state.counter + 1 },
  effects.none(),
];

const dispatch = app({
  init: [
    { counter: 0 },
    effects.act(IncrementCounterByOne), // run an action via effect
  ],
});

dispatch(IncrementCounterByOne); // run an action via dispatch
```

### Action Builder

Action builders are actions that can take parameters. This may mean a value can be passed from user input, or from some other external side-effect. Using the previous counter example, here's what it would look like if it took external input for the increment amount:

```javascript
import { effects } from 'ferp';

const IncrementCounterByN = (n) => (state) => [
  { ...state, counter: state.counter + n },
  effects.none(),
];
```

Similar to naked actions, there are two ways to run this action in your application:

```javascript
import { app, effects } from 'ferp';

const IncrementCounterByN = (n) => (state) => [
  { ...state, counter: state.counter + n },
  effects.none(),
];

const dispatch = app({
  init: [
    { counter: 0 },
    effects.act(IncrementCounterByN(10)), // run a builder action via effect
  ],
});

dispatch(IncrementCounterByN(999)); // run a builder action via dispatch
```

If you're not sure how the builder works, this is just a function that returns a function. Here's probably a more familiar version to read:

```javascript
import { effects } from 'ferp';

function IncrementCounterByNBuilder(n) {
  return function IncrementCounterByNAction(state) {
    return [
      { ...state, counter: state.counter + n },
      effects.none(),
    ];
  };
};
```

This is called a closure, and it's used in Javascript to encapsulate a scope. For instance, the variable `n` is available in the inner function (`IncrementCounterByNAction`), but `n` is not available outside of this closure (`IncrementCounterByNBuilder`).

To make this easier to understand, once we have this builder that returns an action, internally, Ferp does something like this:

```javascript
// You call...
dispatch(IncrementCounterByNBuilder, 999);

// Ferp does...
const yourAction = IncrementByNBuilder(999);
dispatch(yourAction);
```


---

# 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-actions-in-ferp/what-is-a-ferp-action.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.
