Splice for All (React MVVM Version 3 Proposal) #13
Pinned
Andrei15193
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
It's time to look at the observable collections in React MVVM. When implementing them initially, I've realized that all mutating operations can be rewritten using
splice
simplifying the implementation.To do this I'll be using the negative indexes that JavaScript implements as it simplifies the calls, illustrates their utility and it brings more awareness to this feature. The observable collections that offer an array-like interface will support this as well making it seamless when working with them.
push
- add items at the end of the collection.pop
- remove an item from the end of the collection.unshift
- add items at the beginning of the collection.shift
- remove an item from the beginning of the collection.fill
- set the same item on multiple indexescopyWithin
- copy (may duplicate) items inside the array from one location to another.This one is a bit more complex compared to the others, the issue being that
copyWithin
never extends an array, for simplicity we can get the max length using a 2nd splice.The additional slicing is used to get JavaScript to normalize the indexes for us and get the actual length. I've done this only to illustrate the example. Instead of creating intermediary arrays we can normalize the indexes ourselves and calculate the length.
Breaking Change:
collectionChanged
EventCurrently, the
collectionChanged
event is alright, but not good enough to allow easy replication of any of the above methods. Initially I wanted to do something interesting using array with an offset start index, but as it turns out, it does not always work.This can be partially achieved by creating an empty array of a specified length and then concatenating the actual array,
new Array(10).concat(myActualArray)
. Some of the methods will iterate only the actual array items and provide the offset index.It seemed like a cool idea, however time has proven it wrong and it turns out that sometimes, depending on the bundling tool you use and what configuration it has, you would get
undefined
indexes. This is extremely odd and not having a consistent way of handling this, I've decided to drop this approach and provide astartIndex
along side the added and removed items.This will simplify the interface as well as make it easy to keep mapped collections in sync.
Synced collections are useful when wanting to retain one source collection and provide different projections for it where items have different properties or methods.
Another use case is for animations, but for this the sync code is a bit more complex as removed items need to be maintained in the collection until the animation finishes. This means that the two collections are not always in sync and the item being removed (has the remove animation playing for it) still exists in the mapped collection leading to an index offset that exist between items when removing them in quick succession. This only happens while the animation is playing.
reverse
andsort
These two methods are different. We could write them using
splice
as well, however this would not be entirely accurate as they do not deal with adding or removing items in an array, but rather they reorder the collection.In the case of
reverse
we flip the items and each changes their location, easy to do with one call tosplice
, however this is not the same forsort
as we may have items that retain their position but the ones around them change. For instance,[1, 4, 3, 2, 5]
gets sorted to[1, 2, 3, 4, 5]
, only index1
and3
are changed.In both cases we could be a bit more extreme and
splice
the entire array which will be reflected as all items were removed and added back in a different order.This works, however the observable collections are provided in the context of MVVM which is an architectural pattern for graphical user interfaces. Whenever we perform operations on collections it may be expected to show an animation, it would be nice to be able to visually see how the collection was reordered having items move around.
Introducing the
collectionReordered
EventThis new event will complement the
collectionChanged
event and together will provide all the necessary notifications allowing subscribers to know when and how a collection was changed.The reordered event will provide information about how the items were moved, it will be enough to iterate over each item move element as they will contain both the current and the previous index and item. Going over the reordering information you will know on which index an item was moved, from which index it was moved and what was the previous item that was replaced.
This allows for an easy and effective way to know where each item has went to and from where.
The Goal
The aim for the React MVVM version 3 observable collection changes is to provide all the necessary information for keeping mapped collections in sync as easy as possible. This includes adding or removing items from the collection, for this the
collectionChanged
event will provide all the necessary information to replicate the operation usingsplice
.The
collectionReordered
event will provide all the necessary information when items have been moved inside the collection, but none have been removed or added. The distinction is important when we handle event subscriptions to individual items as well as allowing for different kinds of animations.The next version will feature 2 new observable collections, the ObservableMap and ObservableSet. Both will be implemented in the same fashion, a read-only base class which contains the full implementation, but the mutating operations are marked as protected and the read-write subclass which only exposes the mutating operations.
This allows for custom extensions of the read-only collections and provide your own methods for adding and removing items.
Beta Was this translation helpful? Give feedback.
All reactions