Navy Penguin Mariachi

    @madappgang/update-by-path

    1.1.19 • Public • Published

    Update by path

    Build Status Coverage Status

    Intent

    It is a function that allows to make immutable alterations to objects. It's meant to reduce the code needed to update a deep value without any mutations. It brings readability by reducing the verbosity.

    Installation

    As simple as that

    npm i --save @madappgang/update-by-path

    import update from '@madappgang/update-by-path';

    Real-world example

    I find this package extremely useful with redux reducers, so I'm going to use one of those as an example.

    First off, let's take a look at what a simple reducer would look like without this package.

      const INITIAL_STATE = {
        isFetching: false,
        list: [],
        error: null,
      };
    
      export default (state = INITIAL_STATE, action) => {
        const { type, payload } = action;
    
        switch (type) {
          case types.FETCH_ATTEMPT:
            return {
              ...state,
              isFetching: true,
            };
          case types.FETCH_SUCCESS:
            return {
              ...state,
              isFetching: false,
              list: payload,
            };
          default:
            return state;
        }
      };

    It can be a lot shorter if we use update from the package

    ...
    
    case types.FETCH_ATTEMPT:
      return update(state, { isFetching: true });
    case types.FETCH_SUCCESS:
      return update(state, { isFetching: false, list: payload });
    default:
      return state;
    
    ...
    };

    Same result. What about a bit more complex alterations?

    Here we got to replace a list element by id:

    ...
    
    case types.REPLACE_BY_ID
      return {
        ...state,
        list: state.list.map((element) => {
          if (element.id === payload.id) {
            return payload;
          }
          return element;
        });
      };
    
    ...

    Let's apply the update function:

    ...
    
    case types.REPLACE_BY_ID:
      return update(state, `list[id=${payload.id}]`, payload);
    
    ...

    Still a single line, and still completely immutable.

    API

    It accepts either 2, or 3 arguments.

    update(object, 'deep.path.to.prop', valueToInsert);
    
    update(object, {
      'deep.path.to.props': valueToInsert,
      'another.path': valueToInsert,
    });

    They are completely identical, though the second option allows to make multiple insertions at a time.

    Create new nodes

    If the path contains nodes that do not exist in the source object, they are going to be created

    update({}, 'deep.path', 'value');
    // { deep: { path: 'value' } }

    Use function as a value

    If you need to generate next value based on the previous one, use a function

    const user = {
      name: 'John',
    };
    
    update(user, {
      name: name => name.toUpperCase(),
    });
    // { name: 'JOHN' }

    Go deep inside arrays

    By value

    const user = {
      skills: ['html', 'javascript'],
    };
    
    update(user, `skills[javascript]`, 'JavaScript');
    // { skills: ['html', 'JavaScript' ] }

    By index

    const user = {
      skills: ['html', 'javascript'],
    };
    
    update(user, `skills[0]`, skill => skill.toUpperCase());
    // { skills: ['HTML', 'javascript' ] }

    By property value

    const user = {
      skills: [{ name: 'html'}, { name: 'javascript' }],
    };
    
    update(user, `skills[name=javascript]`, { name: 'JavaScript' });
    // { skills: [{ name: 'html'}, { name: 'JavaScript' }] },

    If there are no matches for your query the source object remains intact.

    Go even deeper inside array elements.

    Alter a property of the matching array element. It doesn't metter which kind of query to use to match the element.

    const user = {
      skills: [{ name: 'html'}, { name: 'javascript' }],
    };
    
    update(user, `skills[name=html].name`, name => name.toUpperCase());
    // { skills: [{ name: 'HTML'}, { name: 'javascript' }] },

    Contribute

    First off, thanks for taking the time to contribute! Now, take a moment to be sure your contributions make sense to everyone else.

    LICENSE

    This project is licensed under the MIT License - see the LICENSE file for details.

    Install

    npm i @madappgang/update-by-path

    DownloadsWeekly Downloads

    1

    Version

    1.1.19

    License

    MIT

    Unpacked Size

    14.6 kB

    Total Files

    7

    Last publish

    Collaborators

    • jackrudenko
    • msalabutin
    • dprovodnikov