Relessjs: state management without Redux’ overhead
Haven’t you been bothered by the sheer amount of work you’d have to put into a project when you use Redux as your state management tool?
Relessjs: state management without Redux’ overhead
Haven’t you been bothered by the sheer amount of work you’d have to put into a project when you use Redux as your state management tool?
Want to use Relessjs immediately? Go to npmjs.com/package/relessjs
Well I have! Especially when the project grows. Then I want to keep things DRY and put my Action Types in one place, because I need to reference them everywhere. Yes, I know, you can still put strings { type: “FILTER" } in there, but then I’ve got to match that to my reducers so that’s already wet (not-DRY).
It’s especially annoying when I’d have to create action factories to do some async stuff. Calling the factory, referencing the action-types, using the type’s in the created actions and, don’t forget it, reducing them.
Implementing search in Redux
Let’s say I have a ToDo app and I want todo’s to be filtered based on text. A simple search feature. To implement this I’d have to do the following:
- add the action type
var actions = { filter: “FILTER” }to todo-actions.js (this is where I put all my constants, to make sure I keep it DRY) - import todo-actions.js into the todo-reducers.js
- create a new case for
actions.filterin thereducer - import todo-actions.js into search-component.js
- implement the
dispatch({ type: actions.filter, payload: event.target.value })in order to get the loop going
Yes, too… much… work… We can do better:
- remove step 1 (no need for an action type);
- remove step 2 (no action-types means: no constants);
- remove step 4 (idem); and
- instead of step 5 (calling
dispatch()), we would just call the reducerreducers.search(payload)and - implement step 3 in the reducer
Implementing search in Reless

Relessjs: Redux without Actions or Dispatcher (made with Asciiflow and Shaky)
I’ve been building Relessjs. A package to provide the same core concepts of the Flux architecture as Redux does but with less overhead.
So now we just call a Reducer from the View and we get a new State on which the View will be rerendered.
Relessjs: unidirectional dataflow without overhead
Now my new search feature for the ToDo app is simplified to only 2 steps:
- Create the reducer named
search(payload)to the list of reducers from Reless - Call the
reducers.search(input.value)from the new search component
Awesome right! Just create and call.
Simplicity: create a reducer, call a reducer
The power of Reless
Below are a few examples of the power that Reless has to offer.
Setting a value, to simply set the state, the reducer is of the following type payload => state: a function that gets a payload and returns a new partial state. Partial state, because it’s being merged with the existing state. This removes the need for an Object.assign({}, value) or { ...state } on the root level.
Incrementing a counter, updating state based on another state:
As shown above (setting a value), you don’t get the state as a second parameter in the first function. To use the state Reless allows you to return a function from the reducer of type state => state. This way you can use the state passed in the second function.
var store = new Reless({
state: { counter: 0 },
reducers: {
increment: payload => state => ({ counter: state.counter + 1 })
}
})
Fetching data, doing some async stuff (and using partial state):
Well, now you know the drill. You can return another function of type reducers => state where you can call another reducer in the same manner as mentioned before and/or return a state that goes effective immediately after finishing the function.
var store = new Reless({
state: { todos: [] },
reducers: {
getAllTodos: payload => state => reducers => {
fetch('some.url/api/todos')
.then((todos) => reducers.setTodos(todos))
return ({ loading: true })
},
// since Reless does a merge we can return
// a partial state instead of a full state
setTodos: todos => ({ todos })
})
Counting down a timer, doing something continuously based on the latest state:
For this we need to do a little trick. Instead of calling a reducer with a payload we call it with another function that returns a payload state => payload. This way we get access to the latest state.
(In the particular case below, you can also just call decrement, but in other cases you might want to call the reducer (setCounter) with a payload)
var store = new Reless({
state: { counter: 20 },
reducers: {
decrement: () => state => ({ state.counter: state.counter-1 }),
setCounter: payload => ({ counter: payload }),
getAllTodos: payload => state => reducers => {
var countdownHandle = setInterval(() => {
if (state.counter)
reducers.setCounter(state => state.counter - 1)
else
clearInterval(countdownHandle)
}, 1000)
}
})
Don’t forget to clap if you liked this. However, if you think something is badly worded, please give me some feedback. I do appreciate it.
메타데이터
- post_id
- b95fbe55784e
- slug
- removing-the-overhead-of-redux-b95fbe55784e
- url
- https://medium.com/@albertg/removing-the-overhead-of-redux-b95fbe55784e
- canonical_url
- https://medium.com/@albertg/removing-the-overhead-of-redux-b95fbe55784e
- author_url
- https://medium.com/@albertg
- status
- ok
- fetched_at
- 2026-07-30 09:45:55