Focalize
Functional Lenses for Javascript
Focalize provides a composable set of functionality to handle immutable data updates.
Example
In order to update state immutably we might use the object spread
operator and map
/ reduce
over arrays as follows:
// vanilla-reducer.js
export const reducer = (state = {}, action) => {
switch (action.type) {
case 'FIRE':
return {
...state,
departments: (state.departments || []).map(department => ({
...department,
employees: (department.employees || []).map(employee =>
(employee.staffId === event.staffId) ? ({
...employee,
terminated: true
}) : employee)
}))
});
default:
return state;
}
};
Focalize increases readibility by providing a composable API that can be used to both query and update data immutably. The same example using Focalize becomes.
// lensed-reducer.js
import { prop, select, every, compose } from 'focalize';
export const reducer = (state = {}, action) => {
switch (action.type) {
case 'FIRE':
return compose(
prop('terminated'),
select(employee => employee.staffId === event.staffId),
prop('employees'),
every(),
prop('department')
).set(state, true);
default:
return state;
}
};
Also note that in the top example if the employee does not exist or is already terminated we still end up with a new state object.
Focalize performs updates economically, we retain the existing
objects if no changes are required, and hence we can use
state === result
to check for changes.
import { reducer as lensedReducer } from './lensed-reducer';
const state = {
departments: [
{
name: 'Research',
employees: [
{
staffId: '101',
name: 'Francis',
terminated: false
},
{
staffId: '123'
name: 'Bob',
terminated: true
}
]
}
]
};
// Bob already terminated, no changes required
assert(lensedReducer(state, {
type: 'FIRE',
staffId: '123'
}) === state); // => OK!
For more examples see the test
folder for basic and advanced usage
as well as usage for each operator.
References
- Monocle
- Scalaz
- Shapeless
- Albert Steckermeier (1 July 2015). "Lenses in Functional Programming".
- Twan Van Laarhoven. "Lenses: viewing and updating data structures in Haskell"