ParcelShape

ParcelShape is a data container very similar to a Parcel but without the automatic data binding. All it does is contain data, no strings attached, and provide methods for you to alter its data.

These exist to be used with updater methods, such as Parcel.modifyDown, to provide a safe way to alter the shape of data in a Parcel. The page on value updaters provides some context.

ParcelShape’s methods are roughly a subset of Parcel’s methods.

import ParcelShape from 'dataparcels/ParcelShape';
import ParcelShape from 'react-dataparcels/ParcelShape';

// it is more like you would encounter these from using shape updaters
import shape from 'dataparcels/shape';
import shape from 'react-dataparcels/shape';
new ParcelShape(value?: any);
  • value ?: any = undefined
    The value you want to put in the ParcelShape. This value will be changed immutably when change methods are called on the ParcelShape. The data type of the value will determine the type of ParcelShape that will be created, and will determine which methods you can use to change the value. Please read Parcel types for more info.
// creates a Parcel that contains a value of 123
let parcelShape = new ParcelShape(123);

Example Usage

ParcelShapes are used in a very similar way to Immutable.js Maps and Lists, by calling methods that return new and updated ParcelShapes.

let modifiedParcel = parcel.modifyDown(shape(
    parcelShape => parcelShape
        .unshift(0)
        .push(4)
        .update(0, value => value * 10)
));

Properties

value

value: any

Returns the ParcelShape’s value.

meta

meta: Object

Returns an object containing the ParcelShapes’s meta data.

data

data: Object

Returns an object containing the ParcelShapes’s data, which includes:

  • value - The ParcelShapes’s value
  • meta - The ParcelShapes’s meta object
  • key - The ParcelShapes’s key
  • child - The ParcelShapes’s child information, which includes any meta, key and child data related to the values children.

key

key: string
key: string

Returns the ParcelShape’s key. Dataparcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info.

Parent methods

get()

get(key: string|number): ParcelShape // only on ParentParcels
get(key: string|number, notSetValue: any): ParcelShape // only on ParentParcels

Returns a ParcelShape containing the value associated with the provided key / index. If the key / index doesn’t exist, a ParcelShape with a value of notSetValue will be returned. If notSetValue is not provided then a ParcelShape with a value of undefined will be returned.

let value = {
    abc: 123,
    def: 456
};
let parcelShape = new ParcelShape(value);
parcelShape.get('abc').value; // returns 123
parcelShape.get('xyz').value; // returns undefined
parcelShape.get('xyz', 789).value; // returns 789

get() with indexed values

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.
let value = ['abc', 'def', 'ghi'];
let parcelShape = new ParcelShape(value);
parcelShape.get(0).value; // returns 'abc'
parcelShape.get(-1).value; // returns 'ghi'
parcelShape.get('#a').value; // returns 'abc'

getIn()

getIn(keyPath: Array<string|number>): ParcelShape // only on ParentParcels
getIn(keyPath: Array<string|number>, notSetValue: any): ParcelShape // only on ParentParcels

Returns a ParcelShape containing the value associated with the provided key path. If the key path doesn’t exist, a ParcelShape with a value of notSetValue will be returned. If notSetValue is not provided then a ParcelShape with a value of undefined will be returned.

let value = {
    a: {
        b: 123
    }
};
let parcelShape = new ParcelShape(value);
parcelShape.get(['a','b']).value; // returns 123
parcelShape.get(['a','z']).value; // returns undefined
parcelShape.get(['a','z'], 789).value; // returns 789

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.

children()

children(): ParentType<ParcelShape> // only on ParentParcels

Returns all of the ParcelShape’s children as new ParcelShapes, contained within the original ParcelShape’s data structure.

let value = {
    abc: 123,
    def: 456
};

let parcelShape = new ParcelShape(value);
parcelShape.children();

// returns {
//    abc: ParcelShape, // contains a value of 123
//    def: ParcelShape // contains a value of 456
// }

toObject()

toObject(): Object<Parcel> // only on parent ParcelShapes

Like children(), expect the returned data structure is cast to an object.

toArray()

toObject(): Object<Parcel> // only on parent ParcelShapes

Like children(), expect the returned data structure is cast to an array.

has()

has(key: string|number): boolean // only on ParentParcels

Returns true if the ParcelShape has a child at the provided key or index, or false otherwise.

size()

size(): number // only on ParentParcels

Returns the number of children this ParcelShape has.

Set methods

set()

set(value: any): ParcelShape
set(key: string|number, value: any): ParcelShape // only on ParentParcels, will set a child

Calling set() with one argument will return a new ParcelShape where the original value is replaced with the value provided.

let parcelShape = new ParcelShape(123);
parcelShape.set(456);
// returns a new ParcelShape containing 456

On ParentParcels this method can also be called with a key, which returns a new ParcelShape with the the child value at that key set to value.

let parcelShape = new ParcelShape({
    value: {
        abc: 123,
        def: 789
    }
});
parcelShape.set('abc', 456);
// returns a new ParcelShape containing {abc: 456, def: 789}

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.

setIn()

setIn(keyPath: Array<string|number>, value: any): ParcelShape // only on ParentParcels

Calling setIn() will return a new ParcelShape where the value at the provided keyPath has been set to value.

let value = {
    a: {
        b: 123,
        c: 789
    }
};
let parcelShape = new ParcelShape(value);
parcelShape.set(['a','b'], 456);
// returns a new ParcelShape containing {a: {b: 456, c: 789}}

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.

delete()

delete(): ParcelShape
delete(key: string|number): ParcelShape // only on ParentParcels, will delete a child

Calling delete() with no arguments will delete the current ParcelShape off of its parent. This variation of the delete() method only exists on ChildParcels.

On ParentParcels this method can be called with a key, which deletes the child value at that key.

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.

deleteIn()

deleteIn(keyPath: Array<string|number>): ParcelShape // only on ParentParcels

Calling deleteIn() will delete the value at the provided keyPath.

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.

update()

// updates value - only to be used if shape doesn't change
update(updater: ParcelValueUpdater): ParcelShape
update(key: string|number, updater: ParcelValueUpdater): ParcelShape // only on ParentParcels, will update a child
type ParcelValueUpdater = (value: any) => any;

// updates shape, including meta
update(shape(shapeUpdater: ParcelShapeUpdater)): ParcelShape
update(key: string|number, shape(updater: ParcelValueUpdater)): ParcelShape // only on ParentParcels, will update a child
type ParcelShapeUpdater = (parcelShape: ParcelShape) => any;

Calling update() with one argument will replace the current value in the ParcelShape with the result of the value updater provided to it. The value updater is passed the current value of the ParcelShape, from which you can return the intended replacement value.

On ParentParcels this method can also be called with a key, which updates the child value at that key. The value updater is passed the current value found at the key, from which you can return the intended replacement value.

Please be careful

This method is safe to use in most simple cases, but in some cases it should not be used:

  • If the updater gives you a primitive value or childless value, you can return anything.
  • If the updater gives you a value that has children, you can always return a primitive value or childless value.
  • If the updater gives you a value that has children, you can return a value with children only if the shape hasn’t changed.

To find out why, and what to do about it, please read about value updaters.

updateIn()

// updates value - only to be used if shape doesn't change
updateIn(keyPath: Array<string|number>, updater: ParcelValueUpdater): ParcelShape // only on ParentParcels
type ParcelValueUpdater = (value: any) => any;

// updates shape, including meta
updateIn(keyPath: Array<string|number>, shape(shapeUpdater: ParcelShapeUpdater)): ParcelShape // only on ParentParcels
type ParcelShapeUpdater = (parcelShape: ParcelShape) => any;

Calling updateIn() will update the value at the provided keyPath. The value updater is passed the current value found at the keyPath, from which you can return the intended replacement value.

Please be careful

This method is safe to use in most simple cases, but in some cases it should not be used:

  • If the updater gives you a primitive value or childless value, you can return anything.
  • If the updater gives you a value that has children, you can always return a primitive value or childless value.
  • If the updater gives you a value that has children, you can return a value with children only if the shape hasn’t changed.

To find out why, and what to do about it, please read about value updaters.

map()

// updates value - only to be used if shape doesn't change
map(updater: ParcelValueUpdater): ParcelShape // only on ParentParcels
type ParcelValueUpdater = (value: any) => any;

// updates shape, including meta
map(shape(shapeUpdater: ParcelShapeUpdater)): ParcelShape // only on ParentParcels
type ParcelShapeUpdater = (parcelShape: ParcelShape) => any;

The map() function will update every child value. It is passed each child value in order, from which you can return each intended replacement value.

Please be careful

This method is safe to use in most simple cases, but in some cases it should not be used:

  • If the updater gives you a primitive value or childless value, you can return anything.
  • If the updater gives you a value that has children, you can always return a primitive value or childless value.
  • If the updater gives you a value that has children, you can return a value with children only if the shape hasn’t changed.

To find out why, and what to do about it, please read about value updaters.

setMeta()

setMeta(partialMeta: Object): ParcelShape

Sets meta at the current parcel’s location. Values on the partialMeta object are merged shallowly onto any existing meta. Read Parcel meta for more info.

Indexed and element change methods

insertAfter()

insertAfter(value: any): ParcelShape // only on ElementParcels, will insert after self
insertAfter(key: string|number, value: any): ParcelShape // only on IndexedParcels, will insert after child

When called with one argument, this inserts value after the current Parcel, within the current ParentParcel.

When called with two arguments, this inserts value after the child Parcel at key.

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.

insertBefore()

insertBefore(value: any): ParcelShape // only on ElementParcels, will insert before self
insertBefore(key: string|number, value: any): ParcelShape // only on IndexedParcels, will insert before child

When called with one argument, this inserts value before the current Parcel, within the current ParentParcel. When called with two arguments, this inserts value as the next sibling Parcel before the child Parcel at key.

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.

move()

move(key: string|number): ParcelShape // only on ElementParcels, will move with sibling
move(keyA: string|number, keyB: string|number): ParcelShape // only on IndexedParcels, will move children

When called with one argument, this moves the current Parcel to the position of key, within the current ParentParcel. Other elements will shift left to fill any gaps left and/or shift right to make room for moved values.

When called with two arguments, this moves the child Parcel at keyA to the position of keyB.

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.

push()

push(...values: Array<*>): ParcelShape // only on IndexedParcels

This triggers a change that pushes all provided values to the end of the current ParentParcel.

pop()

pop(): ParcelShape // only on IndexedParcels

This triggers a change that pops the last value off of the end of the current ParentParcel.

shift()

shift(): ParcelShape // only on IndexedParcels

This triggers a change that pops the first value off of the start of the current ParentParcel.

swap()

swap(key: string|number): ParcelShape // only on ElementParcels, will swap with sibling
swap(keyA: string|number, keyB: string|number): ParcelShape // only on IndexedParcels, will swap children

When called with one argument, this swaps the current Parcel with the one at the position of key, within the current ParentParcel.

When called with two arguments, this swaps the child Parcel at keyA with the one at the position of keyB.

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.

swapNext()

swapNext(): ParcelShape // only on ElementParcels, will swap with next sibling
swapNext(key: string|number): ParcelShape // only on IndexedParcels, will swap child with next child

When called with no arguments, this swaps the current Parcel with its next sibling Parcel, within the current ParentParcel. If called on the last child, it swaps with the first child.

When called with one argument, this swaps the child at the position of key with the next sibling Parcel.

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.

swapPrev()

swapPrev(): ParcelShape // only on ElementParcels, will swap with previous sibling
swapPrev(key: string|number): ParcelShape // only on IndexedParcels, will swap child with previous child

When called with no arguments, this swaps the current Parcel with its previous sibling Parcel, within the current ParentParcel. If called on the first child, it swaps with the last child.

When called with one argument, this swaps the child at the position of key with the previous sibling Parcel.

When called on a Parcel with an indexed value, such as an array, this method can accept an index or a key.

  • index (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence.
  • key (string) is used to get a specific value by its unique key within the Parcel.
Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info.

unshift()

unshift(...values: Array<*>): ParcelShape // only on IndexedParcels

This triggers a change that unshifts all provided values to the start of the current ParentParcel.

Type methods

isChild()

isChild(): boolean

Returns true if the parcel is a child parcel. Read Parcel types for more info.

When a parcel is a child parcel, it allows the use of child methods.

isElement()

isElement(): boolean

Returns true if the parcel is an element parcel. Read Parcel types for more info.

When a parcel is an element parcel, it allows the use of element methods.

isIndexed()

isIndexed(): boolean

Returns true if the parcel is an indexed parcel. Read Parcel types for more info.

When a parcel is an indexed parcel, it allows the use of indexed methods.

isParent()

isParent(): boolean

Returns true if the parcel is a parent parcel. Read Parcel types for more info.

When a parcel is a parent parcel, it allows the use of branch methods and parent methods.

isTopLevel()

isTopLevel(): boolean

Returns true if the parcel is a top level parcel. Read Parcel types for more info.