next.js with mobx

關于狀態(tài)管理

為什么需要狀態(tài)管理?

  • 因為層次深,很不爽

為什么是mobx,而不是redux或者直接context

  • redux 用好久了窿祥,嘗試下新的只冻,樣板代碼太多了庇麦,很不爽
  • context 不推薦不是?
  • ?什么函數式喜德,個人見智
  • 聽說mobxvuex一個道理山橄,我試試
  • mobx 代碼好少,哇舍悯,可以提前下班了航棱,爽

mobx 介紹

這個不用介紹了吧睡雇,自己google

next 介紹

這個我也不管, ssr饮醇、同構嘛它抱,也就那回事。

next 引入mobx

配置啥的(for decorators)

  • babel 6
npm i --save-dev babel-plugin-transform-decorators-legacy

.babelrc

{
    "presets": ["es2015", "stage-1"],
  "plugins": ["transform-decorators-legacy"]
}
  • babel 7
// .babelrc
{
  "presets": [
    "react",
    "es2015",
    "stage-1"
  ],
  "plugins":[
      "transform-decorators",
      ["transform-class-properties", { "loose": true}]
  ]
}

// package.json
{
    "babel-core": "7.0.0-beta.3",
    "babel-preset-es2015": "7.0.0-beta.3",
    "babel-preset-react": "7.0.0-beta.3",
    "babel-preset-stage-1": "7.0.0-beta.3",
    "babel-plugin-transform-decorators": "^6.24.1"
}

兩個方案

  • 統一管理多個 store
import A from './mobx/A'
import B from './mobx/B'

const aStore = new A();
const bStore = new B();

const stores = {
    aStore,
    bStore,
}

class App extends Component {
    render() {
        return (
            <Provider {...stores}>
                <Home/>
            </Provider>
        );
    }
}

export default App;

如上朴艰,簡單的一種引用方式观蓄。next 改造同方案二。

  • 單 page 單store

由于在我項目中呵晚,各個模塊不耦合蜘腌,路由間不想干,所以各自處理就ok饵隙。
ssr 中要解決的一個很大的問題就是 server 和 client 之間狀態(tài)同步的問題撮珠。如下:

// with-mobx-state.js
import React from "react";
import { Provider } from "mobx-react";

export default (initializeStore, storeName, initState = {}) => App => {
  const isServer = typeof window === "undefined";

    // cache
  function getOrCreateStore(initialState = initState) {
    if (isServer) {
      return initializeStore(isServer, initialState);
    }

    if (!window[storeName]) {
      window[storeName] = initializeStore(isServer, initialState);
    }
    return window[storeName];
  }

  return class AppWithMobx extends React.Component {
    static async getInitialProps(ctx) {
      const mobxStore = getOrCreateStore();
      ctx.mobxStore = mobxStore;

      let appProps = {};
      if (typeof App.getInitialProps === "function") {
        appProps = await App.getInitialProps.call(App, ctx);
      }

      return {
        ...appProps,
        initialMobxState: mobxStore
      };
    }

    constructor(props) {
      super(props);
      // sync
      this.mobxStore = getOrCreateStore(props.initialMobxState);
    }

    render() {
      const store = { [storeName]: this.mobxStore };
      return (
        <Provider {...store}>
          <App {...this.props} {...store} />
        </Provider>
      );
    }
  };
};

// testStore.js
import { action, observable } from "mobx";

// 注意模塊內變量的作用范圍: 模塊內是全局的,模塊間是獨立的
let store = null;

class Store {
  @observable lastUpdate;
  @observable light = false;

  constructor(isServer, lastUpdate) {
    this.lastUpdate = lastUpdate;
  }

  @action
  start = () => {
    this.timer = setInterval(() => {
      this.lastUpdate = Date.now();
      this.light = true;
    }, 1000);
  };

  stop = () => clearInterval(this.timer);
}

export default function initializeTestStore(
  isServer,
  { lastUpdate = Date.now() }
) {
  if (isServer) {
    return new Store(isServer, lastUpdate);
  } else {
    if (store === null) {
      store = new Store(isServer, lastUpdate);
    }
    return store;
  }
}

// test.js
import React, { Component } from "react";
import { Card, Button } from "antd";
import { inject, observer } from "mobx-react";
import moment from "moment";
import withMobxStore from "../../decorators/with-mobx-store";
import initializeTestStore from "./testStore";

@withMobxStore(initializeTestStore, "testStore")
class MobxTest extends Component {
  static async getInitialProps(ctx) {
    return {
      title: "mobx test",
      PageHeaderVisible: true
    };
  }

  render() {
    return (
      <Card title="I'm parent">
        <TestChild1 />
        <TestChild2 />
      </Card>
    );
  }
}
export default MobxTest;

@inject("testStore")
@observer
class TestChild1 extends Component {
  render() {
    const { testStore = {} } = this.props;
    return (
      <Card title="I'm child1">
        <code>{JSON.stringify(testStore)}</code>
        <br />
        <br />
        <Button onClick={testStore.start}>start</Button>
      </Card>
    );
  }
}

@inject("testStore")
@observer
class TestChild2 extends Component {
  render() {
    const { testStore } = this.props;
    console.log("testStore.lastUpdate", testStore.lastUpdate);
    return (
      <Card title="I'm child2" style={{ marginTop: 20 }}>
        {/*<code>{testStore.lastUpdate}</code>*/}
        <br />
        <br />
        <Button onClick={testStore.stop}>stop</Button>
        <p>{moment(testStore.lastUpdate, "x").format("YYYY-MM-DD HH:mm:ss")}</p>
      </Card>
    );
  }
}

留有問題:上邊initState其實是沒有意義的金矛。
解決方案: 沒想到芯急。求大佬指教。

TL;DR

  • 存在即合理
  • 對癥下藥驶俊。別再說啥啥啥比啥啥啥好了娶耍。
  • 能快速抓老鼠的都是好貓。
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末饼酿,一起剝皮案震驚了整個濱河市榕酒,隨后出現的幾起案子,更是在濱河造成了極大的恐慌故俐,老刑警劉巖想鹰,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異药版,居然都是意外死亡辑舷,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門槽片,熙熙樓的掌柜王于貴愁眉苦臉地迎上來何缓,“玉大人,你說我怎么就攤上這事还栓÷道” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵剩盒,是天一觀的道長谷婆。 經常有香客問我,道長,這世上最難降的妖魔是什么波材? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮身隐,結果婚禮上廷区,老公的妹妹穿的比我還像新娘。我一直安慰自己贾铝,他們只是感情好隙轻,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著垢揩,像睡著了一般玖绿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叁巨,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天斑匪,我揣著相機與錄音,去河邊找鬼锋勺。 笑死蚀瘸,一個胖子當著我的面吹牛,可吹牛的內容都是我干的庶橱。 我是一名探鬼主播贮勃,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼苏章!你這毒婦竟也來了寂嘉?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤枫绅,失蹤者是張志新(化名)和其女友劉穎泉孩,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體撑瞧,經...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡棵譬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了预伺。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片订咸。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖酬诀,靈堂內的尸體忽然破棺而出脏嚷,到底是詐尸還是另有隱情,我是刑警寧澤瞒御,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布父叙,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏趾唱。R本人自食惡果不足惜涌乳,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望甜癞。 院中可真熱鬧夕晓,春花似錦、人聲如沸悠咱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽析既。三九已至躬贡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間眼坏,已是汗流浹背拂玻。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留空骚,地道東北人纺讲。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像囤屹,于是被迫代替她去往敵國和親熬甚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內容