1.0.1 • Published 5 years ago
@radio/next-mobx-wrapper v1.0.1
next-mobx-wrapper
Mobx wrapper for Next.js
Features
- Simple API, easy steps to set up
- Multiple stores injection
- Works fine with Observable Maps
Installation
To install the stable version you can use:
$ npm i next-mobx-wrapper --save
Usage
Step 1: Wrap withMobx HOC
to _app.js
// pages/_app.js
import ErrorPage from "next/error";
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 {
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (typeof Component.getInitialProps === "function") {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps };
}
render() {
const { Component, pageProps, store } = this.props;
const { statusCode } = pageProps;
if (statusCode && statusCode >= 400) {
return <ErrorPage statusCode={statusCode} />;
}
return (
<Container>
<Provider {...store}>
<Component {...pageProps} />
</Provider>
</Container>
);
}
}
export default withMobx(getStores)(MyApp);
Step 2: Make stores
- 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;
}
const userPromise = yield fetch(`https://api.domain.com/users/${id}`).then(
response => response.json()
);
this.userRegistry.set(id, userPromise.data.user);
});
getUserById = id => {
return this.userRegistry.get(id);
};
}
// Make sure the store’s unique name
// AND getCounterStore, counterStore must be same formula
// Example: getUserStore => userStore
// Example: getProductStore => productStore
export const getUserStore = getOrCreateStore("userStore", Store);
- Make the
rootStore
:
// stores/index.js
// Just only simple
export { getCounterStore } from "./counter";
export { getUserStore } from "./user";
Step 3: Binding data
- 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);
if (!user) {
return {
statusCode: 404,
};
}
return {
user,
};
}
render() {
const { user } = this.props;
console.log(user);
return <div>Username: {user.name}</div>;
}
}
export default User;
- Or any components
// components/UserInfo.jsx
import {inject, observer} from 'mobx-react';
@inject(({userStore: {getUserById}}, props) => ({
user: getUserById(props.id),
}))
class UserInfo extends React.Component {
static propTypes = {};
render() {
console.log(this.props.user);
return <div>Username: {this.props.user.name}</div>;
}
}
// Somewhere
<SampleThing>
<UserInfo id={9}>
</SampleThing>
API
import { withMobx, BaseStore, getOrCreateStore } from "next-mobx-wrapper";