Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 15:14
    FredyC commented #2638
  • 12:42
    MariiaIasakova labeled #2638
  • 12:42
    MariiaIasakova opened #2638
  • Nov 23 20:05
    FredyC unlabeled #2637
  • Nov 23 20:05
    FredyC labeled #2637
  • Nov 23 20:05
    FredyC closed #2637
  • Nov 23 18:35
    urugator commented #2637
  • Nov 23 18:05
    pinonpierre commented #2637
  • Nov 23 18:05
    pinonpierre commented #2637
  • Nov 23 17:00
    FredyC reopened #2637
  • Nov 23 17:00
    FredyC labeled #2637
  • Nov 23 17:00
    FredyC commented #2637
  • Nov 23 16:59
    FredyC closed #2637
  • Nov 23 16:59
    FredyC commented #2637
  • Nov 23 16:49
    pinonpierre labeled #2637
  • Nov 23 16:49
    pinonpierre opened #2637
  • Nov 23 16:17
    FredyC commented #2636
  • Nov 23 16:16
    FredyC unlabeled #2636
  • Nov 23 16:16
    FredyC unlabeled #2636
  • Nov 23 16:16
    FredyC closed #2636
Ghost
@ghost~5bddb2a3d73408ce4fadbd8b
Consider me forewarned :D
What I'm trying to do is avoid change -> reaction -> change -> reaction while building client side indexes
I need both changes to render at once
Daniel K.
@FredyC
yes, it's tricky :)
Tristan Shelton
@strutcode

Hi, it's been a while since I've used mobx, but I'm having trouble understanding why this doesn't work as expected:

const foo = observable({ bar: observable(['baz']) })

autorun(() => {
  console.log(foo.bar)
})

foo.bar.push('bax')

Expected output would be:

[ 'baz' ]
[ 'baz', 'bax' ]

But actual output is:

[ 'baz' ]
Ghost
@ghost~5bddb2a3d73408ce4fadbd8b
Side note: you don't need to wrap the inner array in observable, the outer observable call will make all current and future property keys observable.
Ghost
@ghost~5bddb2a3d73408ce4fadbd8b

(deleted my earlier message as it was incorrect)

@strutcode I believe what's happening is that the autorun is only pointing at the reference to foo.bar, which does not change when you push a new value. It's the same array instance, so nothing actually changes in the autorun function when the array grows.

If the autorun refers to something that does change when you push (like the length of the array) you will see it run twice as you expect. Here's an example:
https://codesandbox.io/s/quiet-hooks-x5izs?file=/src/index.js
If you had an observer that, for instance, looped over the values in the array, it would trigger for your change.
siimsaar
@siimsaar
Why does Mobx6 remove fields that are functions from map? Is it by design?
Arrow functions to be specific
Michel Weststrate
@mweststrate
yes, datastructures like Map, Set and array should be kept clean
siimsaar
@siimsaar
ok, but is there a workaround for this or is converting maps to objects the only option?
Michel Weststrate
@mweststrate
@sdothaney_twitter console.log is a really tricky tool to test reactivity as it is an asynchronous method in most runtime environments,
put your methods somewhere else? I recommend in general to use maps for dynamic lookup structures and objects for statically shaped structures
Tristan Shelton
@strutcode
@sdothaney_twitter Interesting. Is there a way to work around that? Ultimately I want to just observe the base object, but detect all changes in all of the fields under it.
And you're right, I originally had only one call to observable but I wanted to be sure since it wasn't reacting and I only saw a couple of references to reactive arrays in the documentation where they were wrapped directly
Tristan Shelton
@strutcode
@mweststrate Ah, if you're referring to my code the object is just an example. Really I just want to detect changes of any sort to an data structure of an unknown type. Specifically I want to use a websocket to reconstruct the object on another instance of the app and then send updates when the object changes. Not the intended use of mobx I know but I've had good experience using the reactivity for other projects so I thought I'd try it out rather than write my own solution using Proxy
Michel Weststrate
@mweststrate
@strutcode I lost your question, I'm not sure how it relates to storing arrow functions on a map. Or do you mean in a map? Probably best open a discussion qustion on GH with some example code
Ghost
@ghost~5bddb2a3d73408ce4fadbd8b
Yeah Michel has a good point on not using console.log for debugging reactivity – if you're actually using the array to do something, chances are you will get the behavior you expect
@strutcode If you loop the array in your observer (which you probably will if you're using it for something), you will trigger a reaction for the push
https://codesandbox.io/s/quiet-hooks-x5izs?file=/src/index.js I updated the codesandbox to just render the array to the DOM, which behaves how you expect
Ghost
@ghost~5bddb2a3d73408ce4fadbd8b

In general, you can't just reference the top level object and get reactivity for all deeply nested properties. Observers will subscribe to the exact properties that they use. Which is nice for only triggering things that need to be updated.

For deep triggering, there are a few options, though I would rarely reach for these:

  • You can clone the full object in your observer... for instance, JSON.parse(JSON.stringify(foo)) would subscribe you to every property in the object (because the stringify uses them all)
  • There is a deepObserve function in the mobx-utils package that will react for any change at any nested level... we use that for monitoring our entire state for undo/redo.
Tristan Shelton
@strutcode
Oh brilliant @sdothaney_twitter I think deepObserve is what I was looking for. Any idea if it's performant? I can look at it but just curious.
Ghost
@ghost~5bddb2a3d73408ce4fadbd8b
I haven't looked deeply but I believe each property listener it creates would be the normal cost (that is, not much). But it would allow you to very quickly explode your number of listeners if you use it as your default approach.
Tristan Shelton
@strutcode
@mweststrate Sorry for the confusion! My question doesn't relate to functions. This is rough code for the idea I'm testing out:
import {
  autorun,
  observable,
  makeObservable,
} from 'mobx'

function networkRemoteInstantiate(obj) {
    // Imagine sending the whole object via websocket for reconstruction on remote
}

function networkRemoteUpdate(obj) {
    // Send just the diff via websocket using some arbitrary format
}

function networkSync(obj) {
    makeObservable(obj)

    networkRemoteInstantiate(obj)
    autorun(() => {
        networkRemoteUpdate(obj)
    })
}

class Thing {
  @observable name = 'Untitled'
  @observable contents = []
}

networkSync(new Thing())
Ghost
@ghost~5bddb2a3d73408ce4fadbd8b
Michel might be able to better comment on the performance implications of deepObserve. In our usage, it's a non-factor when used for one-offs like undo/redo and persistence. We deepObserve our entire state (thousands of proxies) with ~0ms reaction times. I'm sure there are memory impacts there as well. But we only use it once.
Tristan Shelton
@strutcode
Obviously there's a lot of refinement to do there but hopefully that conveys the concept
Ghost
@ghost~5bddb2a3d73408ce4fadbd8b
Oh yeah - that's exactly what we use deepObserve for besides undo/redo, for syncing changes to the server.
One nice piece, deepObserve gives you an IChange object that just includes the path to the change and the diff... so if you want to, you don't have to send the entire state to the server on every change. If you go that route, your server needs to be able to take changes and merge them back in.
Tristan Shelton
@strutcode
Yes, exactly. I was eyeing that feature for sure haha
Ghost
@ghost~5bddb2a3d73408ce4fadbd8b
Or you can disregard the Change it gives you and just use the function as a trigger to send the whole thing
Tristan Shelton
@strutcode
It's a nice stable existing implementation of basically exactly what I want
All I would really have to do is figure out how to re-apply the change object on the other end
Ghost
@ghost~5bddb2a3d73408ce4fadbd8b
Yep
That's what we do... websockets and all... it works great. The only trouble is when two clients send conflicting changes at the same time (if you have multiple clients working on the same state). But that's a whole topic on its own.
Tristan Shelton
@strutcode
Yeah that could be a problem. In my case it's server authoritative though so no issue there. I want to keep the client dumb and thin
Agost Biro
@abiro
Hi, I'm wondering if I understand correctly that the behaviour of observable.struct and observable.shallow are identical for collections?
swinSpo
@swinSpo
hi
i am trying to do an auto save feature but it seems like i cant get it to work correctly, it seems to run in a loop
i looked at this example from here:
https://mobx.js.org/defining-data-stores.html
but i am trying to add a delay as to when to contact the server. Shouldn't it be as easy as adding the delay option to the example above?
        reaction(
            () => this.jsonA, // Observe everything that is used in the JSON.
            json => {
                // If autoSave is true, send JSON to the server.
                if (this.autoSave) {
                    console.log("jsonA autoSave on")
                    this.update()
                }else {
                    console.log("jsonA autoSave off")
                }
            }, {delay: 5000}
        )
basically, i have this piece of code
    @action.bound update() {
        this.autoSave = false;

        axiosInstane.post("/update", someData)
            .then((response) => {
                if (response.data.success) {
                    this.res = response.data.data
                }
            })
            .catch((error) => {
                console.log(error)
            }).finally(() => {
                this.autoSave = true;
            })
    }
swinSpo
@swinSpo
this does not work because i am setting this.autoSave to true right after i change the state. And because the reaction waits 5 seconds, it will already be set to true and then upload the new state in a loop.
How can i still make use of the delay in state changes? I dont want to contact the server on every single state changes, I'd like to "batch" it into 5 seconds or so and then make the network call
swinSpo
@swinSpo
anyone still on?
Stephen Haney
@StephenHaney
@swinSpo The issue seems more with the autosave logic than the mobx reaction, but are you trying to prevent your update from firing again until you get a response back from the server?
We use the lodash throttle function to achieve the same result, but we don't worry if we've heard back from the server or not before sending another update