lenscrafter

1.2.5 • Public • Published

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 Properties
const someList = initialState.someList;
const someNestedValue = initialState.someList.someNestedValue;
// Object Destructuring
const { 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

import initialState from './state';
// function to retrieve value with fallback
const someNestedProperty = (state) => {
   const { someNestedProperty } = state;
   return state || initialState.someNestedProperty;
};
 
const someNestedValue = (state) => {
   const { someNestedValue } = someNestedProperty(state);
   return someNestedValue || initialState.someNestedProperty.someNestedValue;
};

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.

A lens is a value that composes a getter and a setter function to produce a bidirectional view into a data structure.

Given that we always know our initial state shape in redux we can create a lens for every property in an object.

import lenscrafter from 'lenscrafter'
const initialState = {
  someList: [],
  someOtherProperty: 1,
  someNestedProperty: {
    someNestedValue: 1,
  },
}
 
const currentState = {
  someList: [],
  someOtherProperty: 1,
  someNestedProperty: {
    someNestedValue: 'New Value',
  },
}
// create getter and setter pairs for every property
const ourSpecialLens = lenscrafter(initialState);
ourSpecialLens.props.someNestedValue.get(/* state */); // 1
ourSpeicalLens.props.someNestedValue.get(currentState); // '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.

    lens.props.item1.id.get()

Deeply nested properties will resolve in a similar way

    const myObject = {
        id: 1,
        x: {
            y: {
                item1: {
                    id: 2,
                },
                item2: {
                    id: 3,
                }
            }
        }
    }
    lens.props.item1.id.get()

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.

Dependents (0)

Package Sidebar

Install

npm i lenscrafter

Weekly Downloads

2

Version

1.2.5

License

MIT

Unpacked Size

593 kB

Total Files

46

Last publish

Collaborators

  • millsky