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

View is not updated after change Array inside Object #2290

Closed
NikolayMakhonin opened this issue Mar 22, 2019 · 4 comments · Fixed by #3394
Closed

View is not updated after change Array inside Object #2290

NikolayMakhonin opened this issue Mar 22, 2019 · 4 comments · Fixed by #3394
Labels

Comments

@NikolayMakhonin
Copy link

NikolayMakhonin commented Mar 22, 2019

(version: 3.0.0-beta.20)

This is not update the view:

obj.arr = obj.arr.sort();
obj.arr[0]++
obj.arr[0] += 1
obj.arr[0] = 2
obj.arr2[0][0]++
obj.arr2[0][0] = 3

See repl

How can I update the view manually?

@Panya
Copy link
Contributor

Panya commented Mar 22, 2019

I think this is related to #2243.

@Conduitry
Copy link
Member

If there's an actual assignment, this should work. It looks like the compiler is inserting the correct calls to $$invalidate. I'm not sure what's going on here but I do think there is a bug.

@Conduitry Conduitry added the bug label Mar 22, 2019
@Panya
Copy link
Contributor

Panya commented Mar 26, 2019

Yep, the $$invalidate calls are correct. But the template is not updated because of these generated conditions:

if ((changed.obj) && t15_value !== (t15_value = ctx.obj.arr2)) {
  set_data(t15, t15_value);
}

From the code:

const update_cached_value = `${value} !== (${value} = ${snippet})`;
const condition =this.node.should_cache
? `(${changed_check}) && ${update_cached_value}`
: changed_check;

The t15_value !== (t15_value = ctx.obj.arr2) part is false for object values (arrays and objects).
Not sure where the right place to fix it. We could fix it by adding a check to the generated code or we can change the node.should_cache property for objects and arrays here:

this.should_cache = (
info.expression.type !== 'Identifier' ||
(this.expression.dependencies.size && scope.names.has(info.expression.name))
);

@jimmywarting
Copy link
Contributor

jimmywarting commented Jun 14, 2020

I used an array myself that i needed to know whenever it was changed by an external non-svelte lib and i did not want to allocate a new copy of the huge array for performance reason.

so i came up with a own proxy observer that dose something like this

function observer(target, fn) {
  return new Proxy(target, {
    apply: (...args) => Reflect.apply(...args, fn()),
    deleteProperty: (...args) => Reflect.deleteProperty(...args, fn()),
    set: (...args) => Reflect.set(...args, fn()),
  })
}

let dataset = observer(
  [], // the source, could be a object also
  () => dataset = dataset // override \w same to let svelte know
);

This will still let ju use push, slice, etc...

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