Skip to content

mergeCollection: individual collection item subscriber is called even if the value did not change #535

Closed
@paultsimura

Description

@paultsimura

When executing mergeCollection, Onyx calls the collection subscriber callback and all the collection items subscribers callbacks, even if those items did not change.

As a result, if there is a React component subscribed to a single collection item (e.g. a specific Report) and uses this item as a hook dependency (e.g. useEffect(..., [report])), the hook is executed every time the collection is merged, even if this specific item did not change.

Suggested solution: call individual collection item subscribers only if the item changes.

Example unit test that should succeed:

            it('should not call a collection item subscriber if the value did not change', () => {
                const connectionIDs = [];

                const cat = `${ONYX_KEYS.COLLECTION.ANIMALS}cat`;
                const dog = `${ONYX_KEYS.COLLECTION.ANIMALS}dog`;

                const collectionCallback = jest.fn();
                const catCallback = jest.fn();
                const dogCallback = jest.fn();

                connectionIDs.push(
                    Onyx.connect({
                        key: ONYX_KEYS.COLLECTION.ANIMALS,
                        callback: collectionCallback,
                        waitForCollectionCallback: true,
                    }),
                );
                connectionIDs.push(Onyx.connect({key: cat, callback: catCallback}));
                connectionIDs.push(Onyx.connect({key: dog, callback: dogCallback}));

                const initialValue = { name: 'Fluffy' };

                const collectionToMerge = {
                    [cat]: initialValue,
                    [dog]: { name: 'Rex' },
                };

                return Onyx.set(cat, initialValue)
                    .then(() => {
                        Onyx.mergeCollection(ONYX_KEYS.COLLECTION.ANIMALS, collectionToMerge);
                        return waitForPromisesToResolve();
                    })
                    .then(() => {
                        expect(collectionCallback).toHaveBeenCalledTimes(3);
                        expect(collectionCallback).toHaveBeenCalledWith({
                            [cat]: initialValue,
                            [dog]: { name: 'Rex' },
                        });

                        expect(catCallback).toHaveBeenCalledTimes(2);
                        expect(dogCallback).toHaveBeenCalledTimes(2);

                        Onyx.disconnect(connectionIDs);
                    });
            });

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions