@pacote/flux-actions
Typed actions and reducers for Flux and Flux-like architectures, including the useReducer
React hook.
Demos
Installation
yarn add @pacote/flux-actions
Usage
createAction<Payload>(type: string)
Action payloads
import { createAction } from '@pacote/flux-actions'
const changeYear = createAction<number>('CHANGE_YEAR')
Calling changeYear(1955)
will generate the following action object:
{
type: 'CHANGE_YEAR',
payload: 1955
}
Action metadata
The action creator supports an optional metadata parameter. For example, changeYear(1955, meta: { test: true })
will create:
{
type: 'CHANGE_YEAR',
payload: 1955,
meta: {
test: true
}
}
Actions with errors
Unlike Flux Standard Actions, the action creator does not handle errors. Instead, consider using monadic objects like Either
to wrap error conditions:
import { createAction } from '@pacote/flux-actions'
import { Either, tryCatch } from 'fp-ts/lib/Either'
const changeYear = createAction<Either<Error, number>>('CHANGE_YEAR')
changeYear(tryCatch(...))
isType<Payload>(creator: ActionCreator<Payload>, action: Action<Payload>)
Checks whether an action matches the provided type. This ensures the action is properly typed inside the guard block.
import { createAction, isType } from '@pacote/flux-actions'
const changeYear = createAction<number>('CHANGE_YEAR')
const action = changeYear(1985)
if (isType(changeYear, action)) {
// action.payload is a number inside the guard
console.log(action.payload)
}
reduceFromState(initialState: State)
Creates a reducer which matches action handlers to appropriate types.
import { createAction, reduceFromState } from '@pacote/flux-actions'
const person = createAction<{ name: string }>('PERSON')
const dog = createAction<{ name: string }>('DOG')
const car = createAction<{ brand: string }>('CAR')
const reducer = reducerFromState({ now: 'None', then: '' })
// Matches multiple actions:
.on([person, dog], (s, a) => ({ now: a.payload.name, then: s.now }))
// Matches a single action:
.on(car, (s, a) => ({ now: a.payload.brand, then: s.now }))
const s2 = reducer(undefined, person({ name: 'Marty McFly' }))
// { now: 'Marty McFly', then: 'None' })
const s3 = reducer(s2, dog({ name: 'Einstein' }))
// { now: 'Einstein', then: 'Marty McFly' })
const s4 = reducer(s3, car({ brand: 'DeLorean' }))
// { now: 'DeLorean', then: 'Einstein' })
Reducing actions with errors wrapped in Either
could look something like this:
import { createAction, reduceFromState } from '@pacote/flux-actions'
import { Either, tryCatch } from 'fp-ts/lib/Either'
type State = {
year: number
error?: Error
}
const changeYear = createAction<Either<Error, number>>('CHANGE_YEAR')
const reducer = reducerFromState<State>({ year: 1985 })
.on(changeYear, (state, { payload } ) => payload.fold<State>(
error => ({ ...state, error }),
year => ({ year, error: undefined })
))
reducer(undefined, changeYear(tryCatch(...)))
License
MIT © Luís Rodrigues.