mobxjs / mobx-react-lite

Lightweight React bindings for MobX based on React 16.8 and Hooks
https://mobx.js.org/react-integration.html
MIT License
2.13k stars 90 forks source link

`useLocalStore` async example #228

Closed bradleygore closed 4 years ago

bradleygore commented 4 years ago

I'm new to using hooks and trying to wrap my head around them, so apologies if this is a dumb question.

If you have a component, say a dropdown, that needs to dynamically load options based on incoming props (but the props won't change after initial load of the component) - can you use useLocalStore to do that? Is there a good example somewhere of how to do that? Every example I can find shows only the simplistic example of just loading some dataset already in memory :)

For example, if this store (taken from https://mobx-react.js.org/state-local) needed to hit an API to load the initialCount, how would that be structured? Or, should we even do that with useLocalStore?

const store = useLocalStore(
    // don't ever destructure source, it won't work
    source => ({
      count: props.initialCount,
      get multiplied() {
        // you shouldn't ever refer to props directly here, it won't see a change
        return source.multiplier * store.count
      },
      inc() {
        store.count += 1
      },
    }),
    props, // note props passed here
  )
bradleygore commented 4 years ago

I was able to achieve this using the react useEffect hook - basically, loading the items, then calling store.setItems. Works well, but would still love to see some more comprehensive examples in the docs :)

danielkcz commented 4 years ago

Well, to be honest, why do you need to use observables at all? I mean options to dropdown sounds like something you just render and don't modify later. If you do then approach through the useEffect is probably the best you can get. The second arg to useLocalStore is designed for simple flat structures, not need ones.

mweststrate commented 4 years ago

...or, if you want to stay in the observable world (doesn't sound needed here), I'd go for reactions instead of effects, and only use a useEffect to clean up the reactions in the end. Combining observables directly with useEffect and friends always get a bit awkward imho, so I'd recommend to express side effects in the same tool as used to capture the state, regardless whether it is mobx or useState.

On Fri, Oct 4, 2019 at 6:43 AM Daniel K. notifications@github.com wrote:

Well, to be honest, why do you need to use observables at all? I mean options to dropdown sounds like something you just render and don't modify manually. If you do then approach through the useEffect is probably the best you can get. The second arg to useLocalStore is designed for simple flat structures, not need ones.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/mobxjs/mobx-react-lite/issues/228?email_source=notifications&email_token=AAN4NBHM3XFIXT4XWWRU2W3QM3JXHA5CNFSM4I5KER5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEAKPT5Y#issuecomment-538245623, or mute the thread https://github.com/notifications/unsubscribe-auth/AAN4NBCYYTOAKH2H5O5GDADQM3JXHANCNFSM4I5KER5A .

danielkcz commented 4 years ago

@mweststrate Funny, but @urugator advocates against using reactions as much as possible.

But let's not dive too deeply here since we don't know the context. I am closing it as answered. @bradleygore if something is still unclear, let us know.

mweststrate commented 4 years ago

I agree :) if side effects are only relevant for components / fit in component life cycle, I'd prefer effects in most cases. It was more of a general statement.

On Fri, Oct 4, 2019 at 10:31 AM Daniel K. notifications@github.com wrote:

Closed #228 https://github.com/mobxjs/mobx-react-lite/issues/228.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mobxjs/mobx-react-lite/issues/228?email_source=notifications&email_token=AAN4NBHJPETHAQDEYROA2BTQM4EN3A5CNFSM4I5KER5KYY3PNVWWK3TUL52HS4DFWZEXG43VMVCXMZLOORHG65DJMZUWGYLUNFXW5KTDN5WW2ZLOORPWSZGOUASR73Y#event-2686787567, or mute the thread https://github.com/notifications/unsubscribe-auth/AAN4NBDFAB4U66TVFEF7ARLQM4EN3ANCNFSM4I5KER5A .

bradleygore commented 4 years ago

Well, to be honest, why do you need to use observables at all?

The Select component I'm dealing with in this case is fully controlled by owning component. You have to tell it when it's showing opts, what is highlighted, etc... though it provides props to receive notification of such things possibly changing, it's still in your control if those changes take effect or not. See the code for their simplest example to see what I mean: instructure-ui Select I like mobx and wanted to deal w/ observables vs setState everywhere.

If useEffect seems like the right approach to y'all, which it seems so and it appears to work well for me thus far, I'll stick w/ that. Thanks!

danielkcz commented 4 years ago

Well, one thing is state like what is currently selected, highlighted, whatever, but you were talking about options which even for that Select component you can see in examples is not part of the state. Of course if you for some reason want to change options dynamically, then it might be useful, but I seriously doubt about that :)

bradleygore commented 4 years ago

@FredyC - maybe I'm missing something, so want to clarify. I'm loading in the options for the dropdown async based on the incoming prop the component is loaded with (and that prop won't change). So, if I want the component to update, I do need the options (as well as custom flags like isLoading, etc..) to be part of the state (observable local state in this case). Right?

danielkcz commented 4 years ago

Depends on how you are updating those options, I assume some timed fetch call? That's just React basics. When you pass new props, it will rerender with those. You definitely don't need to have everything in state, that's contraproductive... I highly recommend reading through this, bit longer but totally worth it.

https://overreacted.io/writing-resilient-components/

bradleygore commented 4 years ago

The options aren't coming in to my component via props. Some ID is coming in on props, and my component is then fetching the options for that ID.

I'm trying to understand nuances of hooks vs class w/ @observer decorator, which is what I've been using the last few years. If using useLocalState, then when the opts are loaded inside the component in question, it has to be stateful else the component won't know to update. That's my entire inquiry.

Thx for the article - will read.