1.0.1 • Published 5 years ago

@radio/next-mobx-wrapper v1.0.1

Weekly downloads
-
License
MIT
Repository
-
Last release
5 years ago

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";