【失った時間:5時間】
こんにちは。ReactNative開発奮闘記が続きます。
今日は、React-MobxのStore Injectionがいつの間にか廃止になっていた件について、まとめておきます。最近、Classベースの実装をFunctionベースの実装に変換している過程で、これまでMobx-Reactを使って書いていた@inejct(“stores”)構文をどうFunctonベースの実装に移植したら良いんだろうとつまづくことがあったので、色々と調べた結果、衝撃の事実に辿り着きました。
Contents
問題
今回、以下のコードをFunctionベースの実装でも使えるようにしようと奮闘していました。
とりあえず、一般的なルールに従って構文を書き換えてみましたが、この状態だとエラーが出てうまく動きませんでした。
Before
import { inject } from "mobx-react";
@inject("stores")
export default class SearchTop extends Component {
After
@inject("stores")
export const SearchTop = (props) => {
## エラー
A decorated export must export a class declaration. (12:0)
原因と解決方法
上の問題では、そもそもまず関数ではアノテーション(@)が利用できない、という問題と、@inject(“Stores”)が利用できないという2つの問題を抱えていました。
1点目については、世界でも困っている人が一定数いて、こんな記事を見つけたりしました。
javascript – Decorators on functions – Stack Overflow
だけど、ここで書かれている通りにworkaroundの実装をしても動かず、「というかそもそも@inject(“stores”)って今推奨された書き方なんだっけ?というところが気になってきたので、mobx-reactの公式ドキュメントを探してみると・・・
あった!
https://mobx-react.js.org/recipes-inject
We are in 2019 now and we don’t need injections anymore (kids, don’t do drugs).
・・・!なんと!笑 衝撃を抑えてさらに読み進めます。
Why is it obsolete?
The main reason is that we have much better tools at our disposal now. The inject pattern is not wrong or broken in general, but it is rather limited and error-prone.In its simplest form
inject('myStore')
(strings, meh!) the wrapped component props get modified and it’s easy to lose track of what’s coming into the component because the string argument does not give you any clue. This can be a source of annoying bugs, and maybe more importantly the pattern is incompatible with a typed language like Typescript. You can read more about the struggles with Typescript in this unresolved issue.An alternative variant of inject allows for reactive selections over the stores to pick the values that the component requires. It can be useful if reused over multiple components, but otherwise it brings similar confusion as the simple form of inject.1
ううむ、なるほど、まあ超簡単にまとめるともっと良い方法があるから廃止した、ということみたいですね。
(私がこのコードを実装した際には、Linked Learningか何かの少し古いコンテンツを参考にしていた気がするので、その時点でも実は廃止されていて、今はこんな書き方をしないのが当たり前なのかもしれないですが・・・)
結局、この公式ページにMigrationの方法も書かれていて、この方法に従って実装することで解決できました。
https://mobx-react.js.org/recipes-migration
before
@inject("stores")
export const SearchTop = (props) => {
after
import { useStores } from '../stores/useStores.store';
export const SearchTop = (props) => {
{ "ストア名" } = useStores()
# useStores.store.tsx
import React from 'react';
import { MobXProviderContext } from 'mobx-react';
//import RootStore from './../stores/index';
export const useStores = () => {
return React.useContext(MobXProviderContext)
おしまい!
[番外編] ReactNativeをもっと学ぶなら・・・
React Nativeをもっとちゃんと学びたい!という方は、こちらにおすすめコンテンツをまとめましたので、ご参考にしていただければと思います・・!
土台のJavaScript/TypeScriptに不安がある方は、こちらもまとめましたので、ご参考になりましたら幸いです。