arqex / freezer

A tree data structure that emits events on updates, even if the modification is triggered by one of the leaves, making it easier to think in a reactive way.
MIT License
1.28k stars 56 forks source link

Object References and relations across state changes? #90

Closed BerndWessels closed 7 years ago

BerndWessels commented 8 years ago

I try to have my own kind of Entity System stored in Freezer Store.

But my Entity Objects have relations - here is an example on how I got it to work in Freezer:

    setTimeout(() => {
      let state = this.props.store.get();
      let app = state.app.transact();
      app.human[0] = {firstName: 'Bernd'};
      app.dog[99] = {name: 'Brutus'};
      state.app.run();

      setTimeout(() => {
        let state = this.props.store.get();
        let app = state.app.transact();
        Object.assign(app.human[0], {lastName: 'Bernd', dog: app.dog[99]});
        state.app.run();

        setTimeout(() => {
          let state = this.props.store.get();
          let app = state.app.transact();
          Object.assign(app.dog[99], {age: 88});
          state.app.run();

        }, 1000);

      }, 1000);

    }, 1000);

at the end

state.app.human[0] is correctly {"lastName":"Wessels","dog":{"age":88,"name":"Brutus"},"firstName":"Bernd"}

But this needs transact() which I am not sure about the performance if the Entity tree is very big.

I tried this, but it didn't work:

  setTimeout(() => {
    let state = this.props.store.get();
    state.app.human.set(0, {firstName: 'Bernd'});
    state.app.dog.set(99, {name: 'Brutus'});

    setTimeout(() => {
      let state = this.props.store.get();
      state.app.human.set(0, Object.assign({}, {lastName: 'Wessels', dog: state.app.dog[99]}, state.app.human[0]));

      setTimeout(() => {
        let state = this.props.store.get();
        state.app.dog.set(99, Object.assign({}, {age: 88}, state.app.dog[99]));

      }, 1000);

    }, 1000);

  }, 1000);
}

but at the end

state.app.human[0] is only {"lastName":"Wessels","dog":{"name":"Brutus"},"firstName":"Bernd"}

even though

state.app.dog[99] is {"age":88,"name":"Brutus"}

Basically what I am asking is - how can I make sure that object references are preserved / distributed in freezer properly and with the best performance.

arqex commented 7 years ago

Hey,

The problem in your code is that you are using Object.assign with immutable objects. I am sure that is making some parts not to update.

Instead, try to do something like.

state.app.human[0].set({lastName: 'Wessels', dog: state.app.dog[99]});

That will keep the reference to your dog in the store, instead of creating a new object with the dog. Also a bit below:

state.app.dog[99].set({age:88});

That will edit the same dog that you were referencing before, so your human will be updated too.