Get rid of your reducer boilerplate!
Zero hassle state management that's typed, flexible and scalable.
npm install riduce
Whether you're using useReducer
or redux
, reducer boilerplate is tedious to learn, setup and maintain.
What if type-safe state management was quicker, easier and simpler?
Riduce is a library written to be:
- Strongly-typed, so your state stays predictable
- Trivial to scale as your state grows more complex
- Zero hassle, with just two lines of code...
... and one of the 2 lines to setup is an import
.
import riduce from 'riduce'
const [reducer, actions] = riduce(initialState)
That's it! Now you've got a type-safe reducer
and arbitrary actions
, with zero hassle.
Let's see it in use!
🚧 Full documentation for Riduce is under construction - but the API is essentially the same as Redux-Leaves, except
riduce
replaces thereduxLeaves
default export. Currently documented here are indicative examples on setup, usage and customisation. These give quite a lot of information about how the library is used. For more specifics, please consult the Redux-Leaves documentation to see, e.g., the default action creators whichcreate
gives access to.
For a useReducer
example, see this CodeSandbox.
For a redux
example, you can run this Repl.it.
For more advanced usage of Riduce, see this example.
Below, we'll walk through the introductory Redux example, showing:
- Zero hassle setup with 2 lines of code;
- Scalable state management with arbitrary actions; and
- Typesafe action creators to mirror your state's shape.
Let's imagine we're controlling the state for a museum.
import { createStore } from 'redux'
import riduce from 'riduce' // 1st line: import
const museumState = {
isOpen: false,
visitor: {
counter: 0,
guestbook: ['richard woz here']
}
}
const [reducer, actions] = riduce(museumState) // 2nd line: setup
const { getState, dispatch } = createStore(reducer)
And that's it. Those two lines replace all of our reducer boilerplate.
Continuing on from above, let's:
- Open our museum;
- Add to the visitor counter;
- Sign the guestbook; and
- Amend a guestbook entry.
Previously, you might create 4 x reducer branches, action types and action creators.
Riducer gets rid of all that boilerplate.
Now, it's as simple as describing the changes we want to see!
// at `state.isOpen`, create an action to toggle the boolean
dispatch(actions.isOpen.create.toggle())
// at `state.visitor.counter`, create an action to add 5
dispatch(actions.visitor.counter.create.increment(5))
// at `state.visitor.guestbook`, create an action to push a string
dispatch(actions.visitor.guestbook.create.push('LOL from js fan'))
// at `state.visitor.guestbook[0]`, create an action to concat a string
dispatch(actions.visitor.guestbook[0].create.concat('!!!'))
getState()
/*
{
isOpen: true,
visitor: {
counter: 5,
guestbook: [
'richard woz here!!!',
'LOL from js fan'
]
}
}
*/
All this is possible because Riduce's actions
gives you loads of convenient action creators out of the box, which you can use liberally throughout your state tree: update
, set
, filter
, reset
, and many more...
It's also possible to add your own in, as documented in advanced Riduce usage.
Now we've seen that Riduce is zero-hassle setup for arbitrary action creators without the reducer boilerplate.
It's written in TypeScript, so it's helpfully typed right out of the box as well!
// can we push to a boolean? no!
// ❌ TypeError: (ts 2339) Property 'push' does not exist on type...
actions.isOpen.create.push()
// can we push to an array without an argument? no!
// ❌ TypeError: (ts 2554) Expected 1-3 arguments, but got 0.
actions.visitor.guestbook.create.push()
// can we push a number to an inferred string[]? no!
// ❌ TypeError: (ts 2345) Argument of type '10' is not assignable to parameter of type 'string'.
actions.visitor.guestbook.create.push(10)
// can we push a string to an inferred string[]? yeah, okay then.
// ✅ compiles!
actions.visitor.guestbook.create.push('10')
You may wish to check out the following:
Advanced Riduce usage includes:
- Bundle multiple actions into a single dispatch;
- Execute arbitrary reducer logic for extendability;
- Add custom reducers for reusability; and
- Control action types for debugging (e.g. Redux DevTools).
Have fun adding it to your project!
npm install riduce
🚧 Full documentation for Riduce is under construction - but the API is essentially the same as Redux-Leaves, except
riduce
replaces thereduxLeaves
default export. Currently documented here are indicative examples on setup, usage and customisation. These give quite a lot of information about how the library is used. For more specifics, please consult the Redux-Leaves documentation to see, e.g., the default action creators whichcreate
gives access to.