Is there the right and simple way to pass a store to components tree like with react-redux's Provider and connect? It seems that the kind of functionality should be in mobx-react but there isn't.
See mobx-connect or react-tunnel
Op ma 2 mei 2016 om 14:23 schreef Sergey Smirnov [email protected]:
Is there the right and simple way to pass a store to components tree like
with react-redux's Provider and connect? It seems that the kind of
functionality should be in mobx-react but there isn't.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
https://github.com/mobxjs/mobx/issues/230
@mweststrate I have tried those. react-tunnel seems to not support stateless functions (I got an error) and the module itself not supported by the author. mobx-connect is similar to react-redux but more verbose.
What method do you use or the right way to pass a store? It seems it is quite common functionality passing a store to components. Do you plan include this functionality to modx-react, for example delegate connect functionality to @observer and add Provider like component?
@smirnovshina why don't you just pass the store as a prop? That's how every other library does it behind the scenes anyways unless it's using context, which is the same concept regardless. The only reason that a library like redux needs provider and connect is because it has a very rigid structure that you have to follow.
With MobX @observer is the same thing as connect, and you shouldn't need a provider or another library to pass down your store...just pass it down. That's what I think anyways.
I tend to agree with @AriaFallah. But people ask on a regular basis for a connector. So the question is should mobx-react maybe provide some standard approach / HoC for working with context? And if so, what should it look like? considering there can be multiple stores in MobX etc.
I'm all about passing it down via props. However, I do get the argument
for context. At times, I'll have a "smart" component hotwire the works to
grab a store out of the ether.
On Mon, May 2, 2016 at 10:22 AM, Michel Weststrate <[email protected]
wrote:
I tend to agree with @AriaFallah https://github.com/AriaFallah. But
people ask on a regular basis for a connector. So the question is should
mobx-react maybe provide some standard approach / HoC for working with
context? And if so, what should it look like? considering there can be
multiple stores in MobX etc.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
https://github.com/mobxjs/mobx/issues/230#issuecomment-216265825
-Matt Ruby-
[email protected]
What about recompose mapProps method?
// MyComponent.jsx
import someStore from '../stores/someStore';
import otherStore from '../stores/otherStore';
export const MyComponent = ({someProp, otherProp}) => (
<div>..{someProp}..{otherProp}..</div>
);
export default mapProps(() => ({
someProp: someStore.someProp,
otherProp: otherStore.nested.otherProp,
}))(MyComponent);
@mweststrate for the multiple stores problem I keep all my stores in one central store using mobx-store. I haven't built anything large or "real world" yet with it though so I think I still need to see if the store of stores idea holds up. I think it will though considering redux kind of does the same thing.
I made a simple Provider and a very simple connect
my store
import {observable, computed} from "mobx"
export default class SessionStore {
@observable user = null;
@observable token = null;
@observable updatingUser = false;
}
export const actions = {}
// action can access all stores
actions.setSessionUserFromServer = stores => json => {
const user = stores.userStore.createOrUpdate(json)
stores.sessionStore.user = user
}
actions.updateSessionUser = stores => user => {
//code
}
and on store index.js
import UserStore, {actions as userActions} from './userStore'
import SessionStore, {actions as sessionActions} from './sessionStore'
export const build = () => {
const store = {
sessionStore: new SessionStore()
userStore: new UserStore()
}
const actions = {
...userAction, ...sessionActions
}
forOwn(actions, (v, k) => ( actions[k] = (...params) => transaction(v(store)(...params)) ))
return {store, actions}
}
a simple Provider:
import { build } from 'stores';
class Provider extends React.Component {
static childContextTypes = {
store: React.PropTypes.object,
actions: React.PropTypes.object
};
getChildContext() {
return {
store: this.appStores.store, actions: this.appStores.actions
}
}
componentWillMount() {
this.appStores = build()
}
render() {
return React.Children.only(this.props.children)
}
}
and a very simple connect
const connect = Component => {
const displayName = `Connect(${getDisplayName(Component)})`
const ObservedComponent = observer(Component)
return class WrappedComponent extends React.Component {
static displayName = displayName;
static contextTypes = {
store: PropTypes.object,
actions: PropTypes.object
};
shouldComponentUpdate(nextProps, nextStats) {
return shallowEqual(nextProps, this.props)
}
render() {
return <ObservedComponent {...this.props} {...this.context} />
}
}
}
Now I just use "connect" on everyplace and the component receive store (with all stores) and actions (with all actions). There is no need to "filter" nothing.
export default connect(MyComponent)
@maxguzenski I'm curious, what's the benefit of doing it this way over just passing it down with props?
@AriaFallah Component can "connect" with stores and actions and use what it want... parent dont need to know everything about its children. If a component want to use something new, just use it, without has to change every component that call this one.
My actions normally need others stores, so, my store are a very stupid classes (just read things, like: call backend for data)... everything that "change data" are actions.
@AriaFallah that is like Relay works, just pass down the minimum that components need to know from its parent, and let component find/load/call everything else.
Sorry if this is a dumb question, but why go through all those hoops?
This is working just fine for me:
//Store.ts
import {observable} from 'mobx';
class Store {
@observable foo: string;
setFoo() {
this.foo = 'test';
}
}
const store = new Store();
export default store;
//ShowFoo.tsx
import Store from './Store';
@observer
export default class ShowFoo extends React.Component<{}, {}> {
componentDidMount() {
Store.setFoo();
}
render() {
return (
<div>{Store.foo}</div>
);
}
}
@luisrudge Yes, You could do that.
But if you want Isomorphic javascript (render on server) that will not work, because you Store is a singleton, and server'll use it to all request, from all users.
ps.: My example was a singleton as well, I updated it.
Good to know, thanks!
Thank you all for answers, situation became clearer. "react-connect" do the job well, but maybe there is no need to use it and just pass a store through props. Most likely people just need to revise some "Redux habits". 😉 Nevertheless it would be great if there were more "best practices" written: how to structure the app, how to solve some common cases, etc...
For other folks coming to this thread, Provider was released with mobx-react: https://github.com/mobxjs/mobx-react#provider-and-inject
Here's a small example:
https://jsfiddle.net/gh/get/library/pure/mattruby/mobx-examples/tree/master/react-examples/20-provider
On Sep 12, 2016 8:46 PM, "Danijel Cole" [email protected] wrote:
Is there an example with Provider in use? I'm having some issues getting
it working with my use case.—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/mobxjs/mobx/issues/230#issuecomment-246549079, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAIrcnmzlENIsMTa8Ii4QYXmww4QYaHzks5qpgBjgaJpZM4IVT0Q
.
Most helpful comment
Sorry if this is a dumb question, but why go through all those hoops?
This is working just fine for me: