justin-schroeder / arrow-js

Reactivity without the framework
https://arrow-js.com
MIT License
2.38k stars 49 forks source link

Array of text boxes without a good key? #91

Closed Clonkex closed 11 months ago

Clonkex commented 11 months ago

First off, thank you SO MUCH for your work on this project! I've gone back and forth on every reactivity framework I could find over the past few weeks, and all of them were either too limited or (WAY) too complex to set up. ArrowJS is a huge breath of fresh air! (Not to mention, this is a work project and I was really stressing that I was going to miss my deadline, either because I couldn't find an appropriate framework or because doing it all by hand was taking a very long time.)

So I'm trying to do this:

<fieldset>
    ${() => addressData.streets.map(
            (streetData, index) => html`
            <div style="margin-bottom: 5px;">
                <input type="text" required value="${streetData}" @input="${e => addressData.street[index] = e.target.value}"/>
                <button type="button" @click="${() => removeStreet(index)}">Remove Street</button>
            </div>
        `.key(index)
    )}
    <button type="button" @click="${() => addStreet()}">Add Street</button>
</fieldset>

The streets array is a plain array of strings. I can't easily change the data, so I'm trying to find a way to work with it as-is. All my other arrays are arrays of objects that have database IDs that I can use as keys, but streets is stored in a weird way in the DB.

If I don't do key(), I have to re-focus the input box after typing each character. I assume this is because all children of <fieldset> are being removed and recreated when the data changes. If I do key(index), the behaviour while typing is jank (first input needs to be refocused, others don't) and I assume removing streets will be broken (the remaining inputs won't get updated properly).

What's the workaround for this situation? Is there something I'm missing or do I just need to get creative?

Clonkex commented 11 months ago

Aha, I got creative lol. I just used @blur instead of @input. Should have thought of that 🤦‍♂️ It's not perfect but this is just a basic admin interface so as long as it works, it's Good Enough™.

justin-schroeder commented 11 months ago

Glad you’re enjoying Arrow! In general the idea here is you want your "components" (functions) to run as infrequently as possible — so in that vein if you can avoid having an input mutate the piece of data that is creating the input itself that will smooth things out a lot.