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

Destructuring in <For> breaks update chain #166

Closed
framp opened this issue Jun 3, 2020 · 4 comments
Closed

Destructuring in <For> breaks update chain #166

framp opened this issue Jun 3, 2020 · 4 comments
Labels
question Further information is requested

Comments

@framp
Copy link

framp commented Jun 3, 2020

It looks like de-structuring in the function passed as children to the components, prevent the system from tracking updates

Minimal example:

import { createState } from "solid-js";

export default () => {
  const [state, setState] = createState({ cards: [{id: 1, used: false},{id: 2, used:true}] });

  const toggle = (targetId) => setState('cards', ({ id }) => targetId === id, 'used', used => !used)
  return (<div>
    <For each={state.cards}>
      {({ id, used }) => (<button onClick={() => toggle(id)}>Marks as {used ? 'unused' : 'used'}</button>) }
    </For>
    <br />
    <For each={state.cards}>
      {(card) => (<button onClick={() => toggle(card.id)}>Marks as {card.used ? 'unused' : 'used'}</button>) }
    </For>
  </div>)
}

Clicking on buttons on the first row doesn't update the used/unused text
The second row does

@ryansolid
Copy link
Member

ryansolid commented Jun 3, 2020

Like MobX or Vue reactivity tracking happens at property access via proxy. This means you want to access them within a tracking scope like a binding or a hook. Unlike React, Vue, or Svelte Solid's granular updates don't update full components or full loop iteration scopes as that would be inefficient as recreating the full components on update would mean recreating the DOM nodes.

I could do a better job documenting this I think. But the example at the beginning of the Components docs explains this a bit. https://github.com/ryansolid/solid/blob/master/documentation/components.md#components

@ryansolid ryansolid added the question Further information is requested label Jun 3, 2020
@framp
Copy link
Author

framp commented Jun 3, 2020

Thanks for the explanation and the library; I'm really enjoying solid and I'm already using it in a toy personal project.

Sorry for the noise, I assumed it was a bug but I see now that you can't really keep track of things if the user removes the Proxy via de-structuring.

Do you think there would be any disadvantage in rewriting de-structuring of Proxy instances at compile time?
I guess the closer to a real object usage we can get, the more user friendly the library is.

@ryansolid
Copy link
Member

ryansolid commented Jun 3, 2020

Yeah that is interesting and something I did consider briefly. Within localized scope it seems like it could be fine on first look. You would also have to look at any sort of variable access that was outside the bindings. To really confidently do this though you'd need to know what was going to be a proxy and what not, at compile time, which would require special syntax unless you want to only have it pertain to local scope, which would create a wierd inconsistency for a library impressing the lightness of components.

The problem for me ultimately came down to capturing intent. Sometimes I destructure on purpose the same way some I don't include some dependencies on React Hooks. It is sometimes intentional not to make something dynamic. Ultimately make these sort of assumptions would always have to err on the side of is dynamic, so we'd end up creating a lot more reactive wrappers unnecessarily. It seemed consistent that in the same way createEffect only tracks what is inside so would bindings. You know that if you dereference a proxy outside a wrapper it isn't going to cause some unexpected side effect re-rendering a part of your view. But this aspect of destructuring particularly function rest parameters is probably the biggest first difference you hit when coming from React.

@framp
Copy link
Author

framp commented Jun 3, 2020

Thanks, that make sense

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants