LoginSignup
2
1

More than 5 years have passed since last update.

mobx-reactのinjectを使っているコンポーネントをrefで参照する方法

Last updated at Posted at 2019-02-24

最初にrefをおさらいする。例えば次のような感じに実装しているとしよう。

class FooComponent extends React.Component<{}, {}> {
  bar: React.createRef<BarComponent>;
  constructor(props: any) {
    super(props)
    this.bar = React.createRef<BarComponent>();
  }
  render() {
    return <BarComponent ref={this.bar} />
  }
}

mobx-reactのinjectデコレータを使っていないコンポーネントに対してこのようにrefでインスタンスを取得した場合はReact.RefObject<T>でラップされたインスタンスが得られるのでthis.bar.currentのようにしてコンポーネントにアクセスすることができる。

ところがBarComponentがinjectデコレータを使っているコンポーネントの場合、this.bar.currentにはmobx-reactで生成されたInjectorという名のオブジェクトが注入される。InjectorはwrappedInstanceというメンバーで参照したいコンポーネントのインスタンスをもっているため、この場合はthis.bar.current.wrappedInstanceというようにアクセスすればよい。

と、ここまでは特に難しいことではないのだがTypescriptの場合に困った問題が生じる。上の実装例のまま実際にコンポーネントを参照するロジックを実装しようとするとcurrentにwrappedInstanceなんていうメンバーはないと怒られてしまう。

それならば、InjectorはIWrappedComponent<T>というインターフェイスのオブジェクトなので次のように宣言を変更すると...

class FooComponent extends React.Component<{}, {}> {
  bar: React.createRef<IWrappedComponent<BarComponent>>;
  constructor(props: any) {
    super(props)
    this.bar = React.createRef<IWrappedComponent<BarComponent>>();
  }
  render() {
    return <BarComponent ref={this.bar} />
  }
}

今度はrender内のrefの箇所でBarComponentを割り当てられないよと怒られる。(実際はLegacyRef<BarComponent>をIWrappedComponent<BarComponent>に割り当てられないというメッセージが出る。)

mobx-reactのinjectデコレータを使うと宣言と異なるクラスのインスタンスが注入されるため、真面目に宣言しようとするとこのようになる。Typescriptのメリットが失われてしまうのは残念だが、injectデコレータを使っているコンポーネントをrefで参照したい場合はanyで宣言する。

class FooComponent extends React.Component<{}, {}> {
  bar: React.createRef<any>;
  constructor(props: any) {
    super(props)
    this.bar = React.createRef<any>();
  }
  render() {
    return <BarComponent ref={this.bar} />
  }
}
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1