0

I have Stores that are array of objects. The Stores are accessed from a popup component that has a 'Done' and 'Cancel' button. My goal is to only update the store when the user clicks on the 'Done' button. If the popup is closed or the 'Cancel' button is clicked, I don't want to update the Store. I thought that I could use a local variable to assign the value of the Store to but even when I update the local variable, it updates the Store as well. Is this how the Stores should work?

Here is the popup component

<script>
    import Button from "./Button.svelte";
    import CategorySectionStore from '../stores/categorySectionStore';
    import CategoryListStore from '../stores/categoryListStore';
    import AccountSectionStore from '../stores/accountSectionStore';
    import AccountListStore from '../stores/accountListStore';
    import PayeeListStore from '../stores/payeeListStore';

    let categorySections = [...$CategorySectionStore];
    let categoryLists = [...$CategoryListStore];
    let accountSections = [...$AccountSectionStore];
    let accountLists = [...$AccountListStore];
    let payeeLists = [...$PayeeListStore];

    export let togglePopup = () => {};
    export let filter;

    const toggleCategoryGroup = (groupID) => {
        for (let list of categoryLists) {
           // console.log(list)
           // console.log('gid: ' + groupID)
            if (list.Id === groupID) {
                list.Checked = !list.Checked;
            }
        }

    }
    
</script>

<div class="popup {filter}">
    <p class="title">{filter}</p>
    <div class="selection">
        <ul>
            <li>Select All</li>
            <li>Select None</li>
        </ul>
    </div>
    <div class="list">
            {#if filter === 'Categories'}
                <ul>
                {#each categorySections as catSection}
                    <li class="section">
                        <input type=checkbox group={catSection.Name} value={catSection.Name} checked={catSection.Checked} on:click={() => toggleCategoryGroup(catSection.Id)}>{catSection.Name}
                    </li>
                    {#each categoryLists as catList}
                        {#if catList.Id === catSection.Id}
                            <li class="section-item"><input type=checkbox group={catSection.Name} value={catList.subName} checked={catList.Checked}>{catList.subName}</li>
                        {/if}
                    {/each}
                {/each}
                </ul>
            {:else if filter === 'Accounts'}
                <ul>
                {#each accountSections as accountSection}
                    <li class="section"><input type=checkbox group={accountSection.Name} value={accountSection.Name} bind:checked={accountSection.Checked}>{accountSection.Name}</li>
                    {#each accountLists as accountList}
                         {#if accountList.Type === accountSection.Name}
                            <li class="section-item"><input type=checkbox group={accountSection.Name} value={accountList.Name} bind:checked={accountList.Checked}>{accountList.Name}</li>
                         {/if}
                    {/each}
                {/each}
                </ul>
            {:else}
                <ul>
                {#each payeeLists as payeeList}
                    <li class="section-item"><input type=checkbox group="payeeSection" value={payeeList.Name} checked={payeeList.Checked}>{payeeList.Name}</li>
                {/each}
                </ul>
            {/if}
    </div>
    <div class="buttons">
        <Button type="secondary" on:click={togglePopup}>Cancel</Button>
        <Button>Done</Button>
    </div>
</div>

Here one the Stores. All of them are the same just different names.

import { writable } from 'svelte/store';

export const CategorySectionStore = writable([]);

export default CategorySectionStore;

1 Answer 1

1

This is not due to the nature of stores but rather because of how JavaScript itself works. When you are spreading the array from the store into a local array, you are only spreading a reference to the actual object. So the items in the array still point to the same place in memory.

If your array of object is 'shallow' (that is there are no nested objects) you could get away with a map and spread technique instead:

const myarray = otherarray.map(item => ({ ...item }))

This will create entirely new object with the same properties. But as mentioned earlier, if one of those properties is an object of it's own it will again be a reference.

1
  • That was it. Thanks! Commented Sep 22, 2021 at 19:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.