Nanananananananana.. Pat Man!

    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.

    Install

    npm i lenscrafter

    DownloadsWeekly Downloads

    1

    Version

    1.2.5

    License

    MIT

    Unpacked Size

    593 kB

    Total Files

    46

    Last publish

    Collaborators

    • millsky