Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Radio button group only renders correctly when using keyed #each #4207

Closed
JohnnyFun opened this issue Jan 4, 2020 · 8 comments
Closed

Radio button group only renders correctly when using keyed #each #4207

JohnnyFun opened this issue Jan 4, 2020 · 8 comments

Comments

@JohnnyFun
Copy link

JohnnyFun commented Jan 4, 2020

Describe the bug
If a radio input group is setup with a filter, the radio button doesn't show as selected upon filtering, unless a keyed {#each} is used. See REPL for example: https://svelte.dev/repl/f40fe70abc134108bfe125fa111254ea?version=3.16.7

image

Expected behavior
Upon filtering "bob", "bobby" should be selected.

Or svelte could warn about these scenarios, if possible, and instruct to use a keyed each. And svelte could fallback to re-rendering entire each block or something so that it at least gets rendered correctly. But not sure on internals...so.

Information about your Svelte project:

  • Chrome Version 79.0.3945.88 (Official Build) (64-bit)

  • Your operating system: Win10

  • Svelte version: 3.16.7

@antony
Copy link
Member

antony commented Jan 6, 2020

This is the behaviour I would expect from an un-keyed array in this scenario.

I'm not sure how feasible it would be to auto-detect the need for a keyed each, or if it is even desirable, so this is more of a docs thing. The issue is I'm not even sure how we could document this without it being TMI for most users. The concept around keying is already documented.

I'll have a look at docs for keying features on similar projects and see if there are any improvements to make.

@JohnnyFun
Copy link
Author

It seems like keyed each blocks should be used whenever possible then? Ideally svelte would warn though when in dev mode if it isn't going to be able to render the each body correctly.

I've run into a few scenarios where each bodies aren't updated correctly. For instance, this issue shows one where it's in a slot: #4165. If a keyed each is used, it works, else it renders the incorrect image.

@JohnnyFun
Copy link
Author

fwiw, I also noticed it renders correctly if I fully reset the value that the each loop is using:

let peopleFiltered = []
$: search, onSearchChanged()
async function onSearchChanged() {
	peopleFiltered = [] // clear array totally
	await tick() // render it empty...
        // then render it with the search applied
	peopleFiltered = search == null || search.trim() === '' ? 
		people : 
	        people.filter(p => p.name.indexOf(search) > -1)
}

@antony
Copy link
Member

antony commented Jan 7, 2020

@JohnnyFun that also makes sense. The keying is designed to track elements, so rewriting the entire list will create new tracking keys internally, and thus render correctly.

The other ticket has been marked as a bug by @Conduitry but I'm not sure that this is the same issue.

@JohnnyFun
Copy link
Author

@antony, yeah I don't think they're the exact same issue, but what seems similar between the two is that svelte mostly updates the UI, but doesn't quite get everything.

I also noticed if I use the object ref as the key in a keyed each, it works correctly (i.e. {#each peopleFiltered as p (p)}). I would've assumed that svelte would be using the object ref as the internal key in a non-keyed each loop, but that must not be the case. Do you know what it does use? Otherwise, I'll look at svelte source later this week and see what it uses to track and update items in a non-keyed each.

Another thing I noticed that makes it render correctly is:

  • select "bobby"
  • filter "bob" (bobby only result, not selected)
  • add "a" to your filter so you have "boba" (no results)
  • back out the "a" so back to filtering "bob" (bobby only result, is selected)

I've been able to work around these not-quite-updated-UI scenarios by doing await tick() prior to setting the value. And if that doesn't work, nulling the value out, await tick, then setting it (as in this particular scenario). It would just be easy to miss this scenario, since at a glance it appears to be working as I want it to.

Here's hoping the fix for the other one either fixes this one too, or shakes something loose that makes it clear why this kind of thing can happen or how svelte might warn about it in dev mode.

@yus-ham
Copy link
Contributor

yus-ham commented Jan 19, 2020

Another thing I noticed that makes it render correctly is:

  • select "bobby"
  • filter "bob" (bobby only result, not selected)
  • add "a" to your filter so you have "boba" (no results)
  • back out the "a" so back to filtering "bob" (bobby only result, is selected)

even if the search box is cleared you will get johnny and bobby selected instead.

@StandUp2001
Copy link

StandUp2001 commented Oct 28, 2023

Tested this issue with the REPL: https://svelte.dev/repl/f40fe70abc134108bfe125fa111254ea?version=3.16.7 from @JohnnyFun (before changing the #each line)
Got the same result with this version (3.16.7)
Now is version 4.2.2 the latest version so tried it with that REPL: https://svelte.dev/repl/f40fe70abc134108bfe125fa111254ea?version=4.2.2 and I couldn't recreate the errors.
So for me it feels like this is already fixed.

@dummdidumm
Copy link
Member

Closing as stale / likely fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants