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

state not updating when it should #111

Closed wrabit closed 5 years ago

wrabit commented 6 years ago

Hello. I have started to integrate Freezer into a project, was going ok but I'm stuck on this niggly issue;

I am using navigator.geolocation.watchPosition() to send new lat/lng coords on update. My reaction hook looks like this:

State.on('app:update_geo', function( geo ) {

    console.log(geo, 'NEW GEO')

    var state = State.get(),
        prevGeo = state.geo;

    // merge with existing geo obj
    state.geo.set({
        ...prevGeo,
        ...geo
    })

    // Calculate distance been the post origin and here
    state.posts.forEach((post, i) => {

        var dist = calcDistances( 
                           post.model.geo.latitude,
                           post.model.geo.longitude,
                           state.geo.latitude,
                           state.geo.longitude );

        post.model.geo.set('dist', dist);
    })

    console.log(state.geo, 'STATE GEO')

    // Update localStorage
    Utils.store('appStorage', state)
});

example console.log outputs: NEW GEO : 50.0621572, 19.9321135 STATE GEO : 51.0621188, 18.9321135

I then push forward a tick(?) by forcing some other update or call the watchPosition again and the STATE GEO catches up to the intended previous, but the NEW GEO could well have changed.

I was sure .now() would have resolved it for me but I have tried .now() on both:

post.model.geo.set({}).now()
state.geo.set({}).now()

with no luck.

For more info I am using this to update the state .on('update') in my App component:

    componentDidMount() {
        var me = this;
        State.on('update', function() {
            me.forceUpdate();
        });
    }

Any pointers appreciated!

arqex commented 6 years ago

Hi,

Keep in mind that after you update the geo object by using state.geo.set() a new state is generated and your state variable is not in the store anymore. Your state is immutable an it will never change. That means that after that command state !== State.get() so you may be not updating the data in the store.

You need to be sure that you are updating the current data in the store. I use a helper function for that:

function st(){ return State.get()}

If you replace state. by st(). in your code it should start working as you want, even if the post.model.geo.set used in the loops trying to update stale data too.