Lens Crafter
A Micro Library for immutable and safe state access
Introduction
This library aims to abstract away the manual creation of lenses or state selectors. In redux we might have an initial state that looks like the following:
const initialState = someList: someOtherProperty: 1 someNestedProperty: someNestedValue: 1
Now we could access these properties a variety of ways.
Dot Properties - The naive approach
// Normal Dot Propertiesconst someList = initialStatesomeList;const someNestedValue = initialStatesomeListsomeNestedValue;
// Object Destructuringconst someList someNestedProperty: someNestedValue = initialState;
But what if the structure of our state changes? This approach will result in an undefined value which could break the UI.
Selectors - A better approach
;// function to retrieve value with fallbackconst someNestedProperty = { const someNestedProperty = state; return state || initialStatesomeNestedProperty;}; const someNestedValue = { const someNestedValue = ; return someNestedValue || initialStatesomeNestedPropertysomeNestedValue;};
This approach is better as it creates a fallback at each level of nesting. But to get a value on state shape change the selectors need to be re-written. Also this does not provide a method by which we can set a value.
Lenses - The Lenscrafter approach.
Given that we always know our initial state shape in redux we can create a lens for every property in an object.
const initialState = someList: someOtherProperty: 1 someNestedProperty: someNestedValue: 1 const currentState = someList: someOtherProperty: 1 someNestedProperty: someNestedValue: 'New Value' // create getter and setter pairs for every propertyconst ourSpecialLens = ;ourSpecialLenspropssomeNestedValue; // 1ourSpeicalLenspropssomeNestedValue; // 'New Value'
using this method, the state retrieval process can be simplified into the one liner above.
It can be ensured that when getting state, a value will always be returned as a fallback instead of undefined
.
API
const newLens = lenscrafter(object)
object
: The object that the lens should be created for.
Usage
newLens.props.property.get(object)
:
object
: The object that the property should be retrieved for. If the object does not have the property it will fallback to the value of the property in the initial call to lenscrafter
.
Returns the current value of the object at the specified property
Property Resolution:
If an object passed into lenscrafter contains a duplicate property. For example:
const myObject = id: 1 item1: id: 2 item2: id: 3
Instead of the id being acessible on the root, it will instead be accessed on it's immediate parent.
lenspropsitem1id
Deeply nested properties will resolve in a similar way
const myObject = id: 1 x: y: item1: id: 2 item2: id: 3
lenspropsitem1id
newLens.props.property.set(value, object)
:
value
: The value to set the property to.
object
: The object for which the value should be set.
Returns a new object with the specified property updated to the specified value
newLens.props.property.lens
:
Returns the lens used for getting and setting, this is useful for further composition.
newLens.getMany(propsArray, object)
propsArray: Array<string>
: An array of properties to get the value of
object
: The object for which the values should be retrieved
newLens.getInitialized()
Returns the initial object passed into lenscrafter(object)
Installation
To install: npm install --save lenscrafter
Contributing
Running tests
Run tests and compile the code with node make
. For tests that also watch the files the karma.conf
can be updated to
be false
for single run, this is particularly useful for development.
Building the code
Code can be built using node make minify
.
Other useful commands
See the scripts
in the package.json for other useful commands.