# Actions

Defining [Redux actions](https://redux.js.org/basics/actions) commonly involves two declarations: an *action type constant* with the `type` value to use, and an *action creator* to generate actions of that type.

```js
// Without Preboiled

const INCREMENT = 'counter/increment'
const DECREMENT = 'counter/decrement'
const MULTIPLY = 'counter/multiply'

const increment = () => ({
  type: INCREMENT
})

const decrement = () => ({
  type: DECREMENT
})

const multiply = amount => ({
  type: MULTIPLY,
  payload: amount
})
```

This is a straight-forward pattern [with several upsides](https://redux.js.org/recipes/reducing-boilerplate#actions), but it's also a quite verbose one. Preboiled's [`createAction`](https://github.com/denisw/redux-preboiled/blob/master/docs/guides/createAction.md) helper, described in this guide, helps you reduce the noise while keeping the benefits. Here is the equivalent code using `createAction`:

```js
// With Preboiled

import { createAction } from 'redux-preboiled'

const increment = createAction('counter/increment')
const decrement = createAction('counter/decrement')
const multiply = createAction('counter/multiply').withPayload()
```

The following sections explain `createAction` and its capabilities in more detail.

## Simple Actions

The `createAction` helper allows you define an action with a single declaration, minimizing boilerplate and room for error. Given an action type value, it returns a matching action creator.

```js
import { createAction } from 'redux-preboiled'

const increment = createAction('counter/increment')

increment()
// => { type: 'counter/increment' }
```

The action type value is made available as a `type` property on the returned action creator (e.g., `increment.type` in the example above). This means you don't need to define a separate action type constant.

```js
increment.type
// => 'counter/increment'
```

The action creator also gets a `matches()` method that compares its `type` with that of a given actions, and returns true if they match. In TypeScript, this method is defined as a \[type predicate]\[ts-type-predicate], so that the compiler can narrow the type of the action in code sections where `matches()` is true:

```ts
if (increment.matches(action)) {
  // The type of `action` is `Action<'increment'>` here
}
```

These additions allow some of Redux Preboiled's other helpers to accept a `createAction` action creator in place of an action type value. For instance, `onAction` (described in the [Reducers guide](https://redux-preboiled.js.org/guides/reducers)) lets you specify the action type by directly passing `increment` instead of `increment.type` or `'counter/increment'`. This is especially beneficial if you use TypeScript, where the action creator's static type is [used for automatic type inference](https://redux-preboiled.js.org/api/onaction#typescript-notes).

By default, the action creators returned by `createAction` produce basic actions with nothing more than a `type`. But this can be changed, as described in the next section.

## Payload Actions

Often, you need to add extra data to actions. For these cases, `createAction` allows you to generate *payload action creators*. These take a single argument and attach it to the returned action as `payload`.

To make a payload action creator, call `.withPayload()` on an action creator returned by `createAction`:

```js
const multiply = createAction('counter/multiply').withPayload()

multiply(2)
// => { type: 'counter/multiply', payload: 2 }
```

In TypeScript, you can specify the type of the payload as a type parameter:

```ts
// TypeScript

const multiply =
  createAction('counter/multiply').withPayload<number>()
```

If you need to attach more than one value to an action, you can use an object as payload:

```js
const logIn = createAction('auth/logIn').withPayload()

login({ username: 'alice', password: 'ecila' })
// =>
// {
//   type: 'auth/logIn',
//   payload: { username: 'alice', password: 'ecila' }
// }
```

## Next Steps

Defining actions is one thing, but you also need the reducers to handle them. Redux Preboiled can help you with that too, as you'll see in the [Reducers guide](https://redux-preboiled.js.org/guides/reducers).
