Mobx wrapper for Next.js
Example: examples/with-mobx-wrapper
$ yarn add next-mobx-wrapper
// pages/_app.js
import {withMobx} from 'next-mobx-wrapper';
import {configure} from 'mobx';
import {Provider, useStaticRendering} from 'mobx-react';
import * as getStores from '../stores';
const isServer = !process.browser;
configure({enforceActions: 'observed'});
useStaticRendering(isServer); // NOT `true` value
class MyApp extends App {
render() {
const {Component, pageProps, store} = this.props;
return (
<Container>
<Provider {...store}>
<Component {...pageProps} />
</Provider>
</Container>
);
}
}
export default withMobx(getStores)(MyApp);
- Create
userStore
sample:
// stores/user.js
import {BaseStore, getOrCreateStore} from 'next-mobx-wrapper';
import {observable, action, flow} from 'mobx';
import fetch from 'fetch';
class Store extends BaseStore {
@observable userRegistry = new Map();
fetchUser = flow(function*(id) {
if (this.userRegistry.has(id)) {
return;
}
try {
const {data} = yield fetch(`https://api.domain.com/users/${id}`).then(
response => response.json(),
);
this.userRegistry.set(id, data);
} catch (error) {
throw error;
}
});
getUserById = id => {
return this.userRegistry.get(id);
};
}
// Make sure the store’s unique name
// AND must be same formula
// Example: getUserStore => userStore
// Example: getProductStore => productStore
export const getUserStore = getOrCreateStore('userStore', Store);
- Create the
rootStore
:
// stores/index.js
export {getCounterStore} from './counter';
export {getUserStore} from './user';
- Any pages
// pages/user.js
class User extends React.Component {
static async getInitialProps({store: {userStore}, query}) {
const {id} = query;
await userStore.fetchUser(id);
const user = userStore.getUserById(id);
return {
user,
};
}
render() {
const {user} = this.props;
return <div>Username: {user.name}</div>;
}
}
export default User;
- Or any components
// components/UserInfo.jsx
import {inject} from 'mobx-react';
@inject(({userStore: {getUserById}}, props) => ({
user: getUserById(props.id),
}))
class UserInfo extends React.Component {
render() {
return <div>Username: {this.props.user.name}</div>;
}
}
// Somewhere
<SampleThing>
<UserInfo id={9}>
</SampleThing>
- Or with Hooks
// components/UserInfo.jsx
import React, {useMemo, useContext} from 'react';
import {MobXProviderContext} from 'mobx-react';
const UserInfo = ({id}) => {
const {
userStore: {getUserById},
} = useContext(MobXProviderContext);
const user = useMemo(() => getUserById(id), [id]);
return <div>Username: {user.name}</div>;
};
export default UserInfo;
Note: Next.js 8
you need add more, if you want to use Observable Maps
//.babelrc
{
"presets": [
[
"next/babel",
{
"transform-runtime": {
"corejs": false
}
}
]
]
}
import {withMobx, BaseStore, getOrCreateStore} from 'next-mobx-wrapper';
MIT © Nghiep