Action
Actions are used to update the state in a predictable way.
Actions are so-called reducers. They take the previous state and a payload and reduce those to the next state.
Actions are the single source of truth in terms of state updates. This pattern is also known as unidirectional data flow.
type Action = (prevState: any, ...payload) => [newState: any, effect?: function]
Note: Actions may also return an optional second item. Read more about effects.
Principles
Since we can't enforce immutability nor pure functions in JavaScript, here are some recommendations on how to write good actions:
- Do not mutate the current state, but rather use immutable data structures
- Ensure that all actions are pure functions
- All actions should have a single responsibility
Pure Functions
A pure function should:
- given the same input, always return the same output
- not mutate the input in any way
- not cause side effects (e.g. API calls)
Example
// number primitivesconst model = 0const actions = { increment: (state) => [state + 1], decrement: (state) => [state - 1],}
// arraysconst model = []const actions = { addItem: (state, item) => [[...model, item]], removeItem: (state, item) => [model.filter((i) => i === item)], clear: () => model,}
// objectsconst model = { firstName: '', lastName: '',}const actions = { updateFirstName: (state, firstName) => [{ ...state, firstName }], updateLastName: (state, lastName) => [{ ...state, lastName }],}