Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Apr 12 18:57
    mweststrate closed #2795
  • Apr 12 18:57
    mweststrate commented #2795
  • Apr 12 10:52
    urugator commented #2876
  • Apr 12 10:47
    urugator commented #2878
  • Apr 12 10:39

    urugator on main

    Fix #2876: Add `defineProperty`… (compare)

  • Apr 12 10:39
    urugator closed #2878
  • Apr 12 10:39
    urugator closed #2876
  • Apr 12 10:34
    urugator commented #2876
  • Apr 12 10:27
    changeset-bot[bot] commented #2878
  • Apr 12 10:27
    urugator synchronize #2878
  • Apr 11 16:16
    changeset-bot[bot] commented #2878
  • Apr 11 16:16
    urugator synchronize #2878
  • Apr 11 13:59
    mweststrate closed #2532
  • Apr 11 13:59
    mweststrate commented #2532
  • Apr 10 14:15

    mweststrate on mobx@6.2.0

    (compare)

  • Apr 10 14:15

    mweststrate on mobx-undecorate@1.1.0

    (compare)

  • Apr 10 13:57

    mweststrate on mobx-undecorate@1.1.0

    (compare)

  • Apr 10 13:57

    mweststrate on mobx@6.2.0

    (compare)

  • Apr 10 13:56

    mweststrate on mobx@6.2.0

    (compare)

  • Apr 10 13:56

    mweststrate on mobx-undecorate@1.1.0

    (compare)

Michel Weststrate
@mweststrate
those links, lol
Les Szklanny
@AjaxSolutions
Would that work with useLocalObservable?
lolive
@lolive
I have this jsFiddle that bothers me a little
Basically, i need to react upon a map being set several times
I cannot find which field must be observed to trigger the reaction all the 3 times in the example
Charlie Matters
@charliematters
wouldn't just using observable.map() make this easier?
Charlie Matters
@charliematters
This works for me, but then it's observing any change in the map - you will probably want to be more specific with your reactions?
var State = {"map":observable.map()};
reaction(
  ()=> State.map.toJSON(), 
  json => {
    console.log("1: map.size: " + State.map.size)
    console.log("1: map.values: " + JSON.stringify(json))
  }
)
Markus Suomi
@MaRaSu

Hello, I'm new to MobX and try to understand some of the new design patterns needed. One area where I could use some guidance is in using MobX observables in situations where I want to read an observable within observer React Component but without causing said Component to track that observable (because it causes unwanted re-renderings). Essentially I just want a snapshot of observable, I do not want to get continuous updates.

That Component is RN Mapview which I have updating observable UI store with map's region coordinates. Whenever I re-render Mapview (in app start or when user switches map layer) I want to use the most recent (also persisted with https://github.com/quarrant/mobx-persist-store) coordinates for setting the Mapview's initial region. However I do not want to get the updates from observable because it just causes unnecessary re-rendering and map movement glitches, I'll just have the user to manipulate the Mapview.

The way I ended up solving it was to have 2 region objects in UI store: one is observable, other one is not. UI store method for updating region updates both so most of the time they are in sync, however the problem is when I hydrate the persisted store in app init: mobx-persist-store only wants to persist observables (it complains for non-observables) so I have an extra "when" reaction to watch hydrating finishing and then initialise non-observable region object from the hydrated observable. Works, but this does not feel terribly elegant. I'm also worried that I'm not yet getting the reactive way to tackle this...

Mali
@Slooowpoke

Real quick question around observables (its quite possible I missed it entirely): I read this: "observable applies itself recursively by default, so all fields in this example are observable"

How deep does this go? Can I have a massive tree with many nested nodes?

let message = observable({
            title: "Foo",
            author: {
                name: "Michel"
            },
            likes: [{
                    name: "John",
                    scores: [{
                            someOtherNestedValue: {
                                moreNestedData: {
                                    0
                                }
                            }
                        }
                    }
                ]
            })

If I wanted to observe acccess to moreNestedData is that going to work?

Michel Weststrate
@mweststrate
yes
Charlie Matters
@charliematters
Sorry to ask one of those "Write my code for me" questions, but I'm upgrading to the latest Mobx (from 6.0.4 to 6.1.5) and I can see that it is now much stricter with inheritance issues.
The docs advise using composition over inheritance, but we use a number of domain objects which extends some basic (abstract) types in a "is-a" rather than "has-a" design, and there are a few functions at the top levels which then automatically trickle down to the instances created. In this case, how would the Mobx hive-mind recommend making this pattern into a composition one instead of an inheritance one?
class BasicEntity {
  @observable id: string | null = null

  private type: string

  constructor(type: string) {
    makeObservable(this)
    this.type = type
  }

  get isNew() {
    return this.id !== null
  }

  get friendlyType() {
    return `This is a ${this.type}`
  }
}
class Child extends BasicEntity {
  // This particular class always has this id
  @override id = 'child'

  constructor(type: string) {
    super(type)
    makeObservable(this)
  }
}
Michel Weststrate
@mweststrate
@charliematters that doesn't mean what you think it means (not even in plain javascript, although it is less observable :). Just set the id in the constructor instead
btw, if it is constant anyway, are you sure it needs to be observable in the superclass at all? If it is constant in all other subclasses as well you don't need that
Charlie Matters
@charliematters
In my case it's observable in almost all subclasses, but defined in a few - the main use case is for typescript type guards. I like the constructor idea though - I feel foolish for not thinking of it! It's nice an explicit and doesn't involve any 'magic'
Ghost
@ghost~5f498a5ad73408ce4fed7a6d
Is there any difference between these two reactions? Does it matter whether the result of the reaction data function is used via the parameter or directly?
reaction(
  () => this.props.value,
  () => this.setValue(this.props.value)
)
reaction(
  () => this.props.value,
  (value) => this.setValue(value)
)
Michel Weststrate
@mweststrate
nope
Bar Ziony
@bartzy
hey! Just upgraded to mobx 6 and encountered some issues. are decorators not working anymore and I must use makeObservable? I read the changelog and blog post but didn't understand if it's required to change or I can keep using decorators.
Hassan Shaikley
@HassanShaikley_twitter
how can I connect mobx to this fiber component?
export default function Player(props) {
    const mesh = useRef()

    useFrame((a) => {

    });

    return (
        <mesh>
            <boxBufferGeometry args={[1, 1, 1]} />
            <meshStandardMaterial color={'orange'} />
        </mesh>
    )
}
Hassan Shaikley
@HassanShaikley_twitter
^ I suppose I figured that out but it has a limitation
Hassan Shaikley
@HassanShaikley_twitter
Can I watch for attempts to change data
But no data was actually changed, ie, the same value was overritten
Markus Suomi
@MaRaSu
Run into a strange problem with Expo (React Native) + mobx + Typescript: when implementing the instructions for "spec compliant transpilation" Fetch API and most of console.log's stopped working in my App when in dev mode (expo start). If I removed the mobx suggested Babel-plugin I got Fetch & console.logging back, however initialisation for observable class fields had the problem that is described in the said mobx installation instructions. However when I changed the babel-plugin config to plugins: [['@babel/plugin-proposal-class-properties', { loose: true }]] both mobx AND Fetch API & console.logging in my Expo App worked properly.
Michel Weststrate
@mweststrate
@bartzy there is a dedicated migration page on the docs, but yes you can keep using decorators if you want, but still need to codemod even in that case
@HassanShaikley_twitter sorry I have no idea what your question is or what it has to do with MobX :)
@MaRaSu sounds like something you want to pick up with expo? maybe they patch fetch / console or something that doesn't work in spec compliant transpiliation?
in loose mode mobx features might not work as inspected, for example declaring fields without initialzing them, or using inheritance. Your code might work if you don't hit any of these cases, but it probably will fail you in a moment where you forgot that you aren't using proper transpiliation config, so I would recommended strongly against it. And obviously we don't accept bug reports in such scenarios
Markus Suomi
@MaRaSu
@mweststrate will raise this with expo team next. What is weird is that I have plenty of ES6 classes declaring properties without initialization and without that babel-plugin it is like you said, they only seem to become observable after getting assigned a value. However with babel-plugin and { loose: true }that problem goes away, i.e. unitiliazed observable class properties work as expected. I do not use inheritance so do not know about that. I tried googling for others using Expo + TS + mobx combo, however I just found pre-mobx6 examples using decorator config.
Markus Suomi
@MaRaSu
@mweststrate it seems I was celebrating early...Soon enough I run into a crash (only on iOS) with react-navigation StackNavigator. Bit of googling which suggested Babel-config might be an issue. Tried various combinations and could not make it work until I went back to Expo's initial babel-config (no plugins, only expo-preset). I declared all my class properties as initialized to "undefined" (if no other sensible value) and mobx seems to be working as expected. @mweststrate any chance you could confirm this workaround fixes the issue of omitting that babel-plugin? Difficult to believe I'm the only one using Expo (TS) + mobx6, so would be keen to hear how others have resolved this babel config prob.
Michel Weststrate
@mweststrate
@MaRaSu since you're using TS, did you update your tsconfig before as well tot he recommended settings? As said I cannot confirm any behavior outside what is specified, but if it works for you, and your code is properly tested you should be ok I guess :)
Markus Suomi
@MaRaSu
@mweststrate yes tsconfig is updated with expo TS settings and with mobx "useDefineForClassFields": true. Let's see how far I get before running into next problem ;=)
RLRabinowitz
@RLRabinowitz
Hey there. I'm using mobx, and my server-side API is mostly REST. I'm looking for a way to cache and manage the state of my data, in a similar fashion of what ApolloClient does: Cache data by ID, get the state of the current cache via loading and error, etc.
I'd like to find a solution similar to ApolloClient, where the main difference is that the data-refresh won't be a GraphQL query, but a Rest API Query, or simply a custom promise.
I couldn't find any package that utilises mobx in such a way.
Does someone here have a suggestion for a package / solution that can help me with managing my data's cache?
Michel Weststrate
@mweststrate
react-query?
Dave Feucht
@davefeucht
I am working on updating mobx in our application from version 4 to version 6. Mostly this is going very smoothly, but we have one case where we have a functional React component that is an observer, and we pass a function to the component as a prop. The function is defined outside the component, but inside the component it is now gets undefined. Other props which are not functions are passed with no issues (string, array, object - I checked all of these). There have been no changes to the related code, only the change in mobx and mobx-react versions (both updated to latest version). Is there something in the mobx configuration that might cause this? In our master branch, the exact same code with mobx 4.15.2 and mobx-react 6.1.1 works without problems. Could it be a mismatch react/mobx-react version? We are using React 16.8.6. If anyone has ideas, let me know.
Michel Weststrate
@mweststrate
@davefeucht are you passing them using an object spread? actions are by default non-enumerable now, so that might cause them to get lost if you pass it like {...object}
RLRabinowitz
@RLRabinowitz
@mweststrate Thanks! react-query seems like a great solution! It does, however, mean that we might be using it instead of mobx altogether
Dave Feucht
@davefeucht
No, they are just being passed like <SomeComponent someFunc={functionName}>. Then if I log someFunc inside SomeComponent it is undefined. And functionName outside the component is definitely defined and has a value (not null).
Dave Feucht
@davefeucht
@mweststrate If I remove the observer() from the component, I do get something from the prop inside the component, as follows:
ƒ res() {
    return executeAction(actionName, autoAction, fn, ref || this, arguments);
}
Michel Weststrate
@mweststrate
@davefeucht hmm that is very strange, afaik we don't filter anything (maybe React.memo does under the hood). I think it is bet to file an issue with a small repro, sounds like it should be trivial to reproduce in a codesandbox
Dave Feucht
@davefeucht
@mweststrate It turns out it was an issue with the default props for that component, which I didn't think to look at since it was working before. So I think we're in the clear :thumbsup:
Hassan Shaikley
@HassanShaikley_twitter

So I have a component that plugs into mobx (state tree to be specific)

useEffect(() => {
const disposer = observe(
store.zone.players.get(props.socket_id),n

And like I am setting up storybook and realizing there is tight coupling going on between the store and the component.

Does anyone know any ways to decouple these things, so that I can test the player component independently of the data in my store.

Alternatively I could just allow them to be tightly coupled and create the player via the store, there's a component that renders players directly from the store. [ The parent of each player ]

What do y'all think

adamsjoe96
@adamsjoe96
I have a store and that contains an array. when the array is modifying the component that needs the array is not rerendered
adamsjoe96
@adamsjoe96
<CustomFlatList data={RootStore.basketStore.getBasketItems} ItemComponent={BasketItem}></CustomFlatList>
let CustomFlatList = observer((props) => {
    const {ItemComponent, data} = props
  return (
    <FlatList
     ...
      renderItem={({item}) => (
        <ItemComponent item={item}></ItemComponent>
      )}
      {...props}
    />
  );
});
let BasketItem = observer((props) => {
  const { item } = props;
  return (
    <Card>
   ...
          <Block style={styles.iconButton}>
            <CustomSpinButton id={item.id} number={item.number}></CustomSpinButton>
          </Block>
       ...
    </Card>
  );
});
let CustomSpinButton = observer((props) => {
  const { id, number } = props;
  return (
    <Block row>
      <Button
        onPress={() => RootStore.basketStore.setItemNumber(id, "minus")}
      ></Button>
      <Button
        onPress={() => RootStore.basketStore.setItemNumber(id, "plus")}
      ></Button>
    </Block>
  );
});
class BasketStore {
basketItems
 visible = false
constructor(rootStore) {
    makeAutoObservable(this);
    this.rootStore = rootStore;    
  }

get getBasketItems() {
      console.log("test")
    return this.basketItems;
  }

setItemNumber(id, operation) {
    let found = this.basketItems.find((item) => item.id === id);
    if (!!found) {
      if (operation === "minus") {
        found.number--;
        if(found.number === 0){
          this.basketItems.splice(this.basketItems.indexOf(found),1)
        }
      } else if (operation === "plus") {
        found.number++;
      }
    }
    else{
        console.log("basket item: ", id , "not found")
    }
  }
I expected that when the setItemnumber function is executed, there is modification of basketItem which should cause CustomFlatList to be rerendered. but nothing happens. Please help me. Thanks!
Sven Helmberger
@fforw
quick question: does mobx have an internal id for observables internally? Even if it's only an index in an array somewhere.
Hassan Shaikley
@HassanShaikley_twitter
how could I force a rerender? I find the state doesnt match the UI bc the UI gets stale, probably when a different tab is open
Markus Suomi
@MaRaSu

Any tips on getting rid of "[mobx] Derivation observer_c is created/updated without reading any observable value"? I have located the React (wrapped in observer() ) component where the problem is (i.e. warning goes away if I take away the reference to problematic observed value), however I cannot figure out why the warning comes. The component works as expected i.e. reacts to the observed value exactly as it should. Observed value is a property in a store, referencing an array of strings where I add (push) and remove (reassign with filter) strings. The warning only comes when I add a new string to the array. My env is react native, with expo and thus without proxy support (if it matters).

I have read MobX documentation over and over again, however have not managed to find tips that would help to further analyse the problem.

Markus Suomi
@MaRaSu
...Continuing on the above: put a trace() in the offending component, it shows (correctly) that "[mobx.trace] 'observer' is invalidated due to a change in: xxxx" again observed value also a correct one. Yet, I get the warning. Now, if I remove in the said component the reference to observed value then the warning goes away, therefore my belief in having located the problem. Most of the time mobx is very nice magic, however when it does not work / provides these warnings it turns into a bit of voodoo magic ;=)
Markus Suomi
@MaRaSu
...Found one culprit. And it was not the React component I initially suspected. Now after some refactoring of the code base I have another warning to chase down. Feels a bit silly to manually remove observer()calls from React components one by one to see when the warning goes away. Analysing the code and trying to see which components truly depend on observable values and which ones do not (and remove observer()calls) sounds simple but has not proven effective enough.