一般社団法人 全国個人事業主支援協会

COLUMN コラム

長らく現場でmobx-react@4を使用しており、
observerでラップされているコンポーネントではhooksが使えず、
そろそろモヤってきたなぁと感じていました。
 
長らくmobx周りの知識もUpdateが止まっていたので、
改めて確認してみるとあらまぁ、
 
mobx-react@6の中にmobx-react-liteが取り込まれているではありませんか!
 
早速更新だ!と動かしたところ



 
エラーでアプリが落ちました(´;ω;`)
 
 
大まかな原因は
 
・これまでWarningにしてたcomponetShouldUpdateの実装が、Errorになること
・SPAでのStoreの差し替えが明示的にErrorになること

 
でした。
(何もかも現コードが悪いです
 
 
さて、前者はまぁさほど大変ではないのですが、
後者はどうすれば良いのかと調べました。
 
mobx-reactが提供するProviderではなく、
いい加減ReactのContextを使えよとのこと。
 
じゃあ差し替えてやんよ!と差し替えたものの、動かず。
 
これまでは各種コンポーネントでStoreを参照する際に、
mobx-reactのinjectを使用していたわけですが、
injectパターンもそろそろやめろよとお達しが出ていました。
 
多分その辺の兼ね合いでダメだったのでしょう。(コードまでは確認していません
 
思いの外大変な作業だぞーぅと作業を開始したわけですが、ところがどっこい。
 
実装方法さえ把握できれば意外とシンプルな見た目で、
差し替えのルーティンを黙々と行うだけですみました。
 
以下が主な実装例です。
(型や一部のexportは省略しているため、おかしなところもあるかも)
 
context

export const StoresContext = React.createContext(null);

export const StoresProvider: React.FC = ({ children, rootStore }) => (
  <StoresContext.Provider
    value={{ rootStore }}
  >
    {children}
  </StoresContext.Provider>
);

hooks

import { StoresContext } from 'context';

export const useStores = () => {
  const store = React.useContext(StoresContext);

  if (!store) {
    throw new Error();
  }

  return store;
};

app

import { StoresProvider } from 'context';
・・・
<StoresProvider rootStore={this.props.store}>
  {/* children */}
</StoresProvider>

component
※injectは削除して、useStores hooksを用いてStoreを参照

import { useStores } from 'useStores';
・・・
const Component: React.FC = () => {
  const { rootStore } = useStores();

  return (...);
};

 
 
ちなみに作業中、
可能な限りClassComponentからFunctionalComponentに変えていたのですが、
state管理がえげつないComponentはそのままにしました。
 
その場合、以下のような形でStoreを参照します。
(詳しくはReact公式のContextの記事を参照してください)
 

import { StoresContext } from 'context';

class Component extends PureComponent {
  render() {
    const { rootStore } = this.context;

    return (...);
  }
}
Component.contextType = StoresContext;
The following two tabs change content below.

江尻 翔

フリーでSEをしています。 バックエンドから逃げて、 現在はフロントエンドメインでお仕事中。

最新記事 by 江尻 翔 (全て見る)

この記事をシェアする

  • Twitterでシェア
  • Facebookでシェア
  • LINEでシェア