with-mobx
MobX stores are not reactive in Next.js v9 when using hooks
"mobx": "^5.11.0",
"mobx-react": "^6.1.1",
"next": "^9.0.1",
"react": "^16.8.6",
Steps to reproduce the behavior, please provide code snippets or a repository:
yarn create next-appmobx and mobx-reactexport default createContext(new Store())const store = useContext(ImportedStore)A re-render should have been triggered by MobX
This bare bones example works fine when using create-react-app instead of create-next-app
import { createContext } from 'react'
import { action, decorate, observable } from 'mobx'
export class PostsStore {
items = [
'Foo',
'Bar'
]
reset() {
this.items = ['Reset']
}
}
decorate(PostsStore, {
items: observable,
reset: action
})
export default createContext(new PostsStore())
import React, { useContext } from 'react'
import { observer } from 'mobx-react'
import PostsStore from '../stores/posts'
const Home = () => {
const store = useContext(PostsStore)
return (
<div>
{store.items.map(item => (<p key={item}>{item}</p>))}
<p>
{/* Clicking reset() DOES NOT trigger a re-render */}
<button onClick={() => store.reset()}>Reset</button>
</p>
</div>
)
}
export default observer(Home)
Also tagging @FredyC to help with this, I am completely stumped
Sorry, I have no experience with NextJS. I just recall a similar issue but doesn't seem there was any conclusion. Perhaps @programbo has some insights?
From my vague knowledge I would perhaps try to utilize Provider instead of setting a store as default value in context. Next might have some issue with globally scoped variables.
fixed
import { createContext } from 'react'
import { action, decorate, observable, computed } from 'mobx'
export class PostsStore {
_items = observable.object({
values: ['Foo','Bar']
})
// this is computed
get items(){
return this._items.values
}
set items(v){
this._items.values = v
}
reset = action(() => {
console.log('resetting items')
// @ts-ignore
this.items = ['Reset']
console.log(this.items)
})
}
export default createContext(new PostsStore())
@jeremy-coleman that’s really help, but maybe not fixed :)
@FredyC any idea why the decorate method wouldn’t work correctly here?
@AndrewBarba Sorry, no idea, I don't use that and never was. Too verbose to my taste.
You’re saying you don’t use decorate? I’m guessing you use the decorator syntax instead? If so I’ll give that a shot. I just want the least, most clear code possible. The example Jeremy posted is way too verbose for my liking
I don't use classes at all, they are so messy 🙊 Decorators are just too weird or maybe I am weird, who knows :) Hooks forever! ✨
Ah okay. So I would really like to use hooks entirely but I struggled with examples that didn’t all use the local store variety. Do you have any suggestions for using hooks that still let us share global stores the way we would with classes?
https://mobx-react.js.org/recipes-context
There a whole lot of information mainly about Hooks.
I’ve read those docs a bunch but I think it finally all makes sense now. I may work on a new simplified example for next that uses the hooks/context/provider approach. Thanks for the help
My example was verbose to show you how mobx works. It proxies objects, which means the ref to the object does not change, which also means you cant make primitives observable. The above code basically just does what observable.box() does. However, The example shows idiomatic use of mobx when you need to intercept the get with a computed. The simples thing is to just make an observable object like let x = observable({}) or observable.map If you want to hand optimize stuff. Also for what youre describing, have a look at undux, its pretty nice
this is all you need to get it to work though
const posts = observable({
items:['Foo','Bar'],
reset:()=>{
posts.items = ['Reset']
}
})
export default createContext(posts)
Thanks thats helpful
I'm creating this https://github.com/oknoorap/mobx-react-lite-context, maybe someone interested.
Usage example: https://codesandbox.io/s/mobx-react-lite-context-3iwcu
I don't really see any benefit of your package against regular React Context. It's kinda funny you actually want a donation for that :D Hard pass.
Besides, how is it related to this issue?
@FredyC it's just for fun 😄 not really want a donation. I don't know maybe someone interested to it, because everyone talking about mobx context, saving their time 😸 . It have hooks, btw.
useContext is not working in functional components when we use nextjs
Hi there! @medmin I was able to get useContext to work with the help of @jeremy-coleman's answer
I was struggling with this too but wanted to keep the class syntax for certain reasons.
I was able to get it working so that you could just do:
import { createContext } from 'react'
import { action, decorate, observable, computed } from 'mobx'
export class PostsStore {
....
}
export default createContext(observable(new PostsStore()))
And then useContext seemed to work. I don't love it, but I hope it helps.
I'm on next 9.4.2 and I can't even get the store initial data even after trying multiples approaches.
Is this a bug with next or the mobx bindings?
We've recently updated our Mobx examples which should address this issue. Thanks!
@Timer Do you have a link to the examples? 🙇
You can find the examples here: https://github.com/vercel/next.js/tree/canary/examples/with-mobx-react-lite / https://github.com/vercel/next.js/tree/canary/examples/
The problem however with this example is the use of useObservable which has been deprecated for some time now.
Most helpful comment
I don't use classes at all, they are so messy 🙊 Decorators are just too weird or maybe I am weird, who knows :) Hooks forever! ✨