Help us understand the problem. What is going on with this article?

React.jsのmixinについて

More than 5 years have passed since last update.

今回はComponentのmixinについて書きたいと思います。

mixinはまさにmixinなので概念自体については説明しませんがComponentの共通な振る舞いをObjectとして共通化することが出来てとても便利です。

React.js自体も、LinkedStateMixinやPureRenderMixinといった形でmixinを提供しています.

ちなみにMarionette.jsでもBehaviorとして、Vue.jsでもmixinとして存在しています。

使い方

使い方はmixinsにObjectを配列として指定するだけです。
配列である通り複数指定することも出来ます。

var Logger = {
  logging(str) {
    console.log(str);
  },
  componentDidMount() {
    this.logging("component did mount");
  }
};

var Hello = React.createClass({
  mixins: [Logger],
  render() {
    this.logging("render");
    return <div>Hello</div>
  }
});

mixinが読み込まれる順番

複数mixinを指定出来るということでどのような順番で読まれるのか確認してみます。

var MixinA = {
  componentWillMount() {
    console.log("mixinA");
  }
};

var MixinB = {
  componentWillMount() {
    console.log("mixinB");
  }
};

var Hello = React.createClass({
  mixins: [MixinA, MixinB],
  componentWillMount() {
    console.log("hello");
  },
  render() {
    return <div>hello</div>
  }
});

React.render(<Hello />, document.body);
// mixinA
// mixinB
// hello

というわけで予想通り、配列の順番で呼ばれて最後にComponentのものが呼ばれるのがわかります。

Conflict State or Prop

ところで、getInitialStategetDefaultPropsなどをmixinで指定するとどうなるのでしょうか。

見てみます。

getInitialState

var Mixin = {
  getInitialState() {
    return {
      mixinValue: "mixin state"
    };
  }
};

var Hello = React.createClass({
  mixins: [Mixin],
  getInitialState() {
    return {
      componentValue: "component state"
    };
  },
  render() {
    console.log(this.state);
    return <div>hello</div>
  }
});

React.render(<Hello />, document.body);
//  Object {mixinValue: "mixin state", componentValue: "component state"}

というわけで値をmergeしてくれます。

getDefaultProps

var Mixin = {
  getDefaultProps: function() {
    return {
      mixinValue: "mixin prop"
    };
  }
};

var Hello = React.createClass({
  mixins: [Mixin],
  getDefaultProps: function() {
    return {
      componentValue: "component prop"    
    };
  },
  render: function() {
    console.log(this.props);
    return <div>hello</div>
  }
});

React.render(<Hello />, document.body);
 Object {mixinValue: "mixin prop", componentValue: "component prop"}

こちらも値をmergeしてくれます。

getInitialStateで同じkeyを指定する

var Mixin = {
  getInitialState() {
    return {
      value: "mixin state"
    };
  }
};

var Hello = React.createClass({
  mixins: [Mixin],
  getInitialState() {
    return {
      value: "component state"
    };
  },
  render() {
    console.log(this.state);
    return <div>hello</div>
  }
});

React.render(<Hello />, document.body);
//  Uncaught Error: Invariant Violation: mergeObjectsWithNoDuplicateKeys(): Tried to merge two objects with the same key: `value`. This conflict may be due to a mixin; in particular, this may be caused by two getInitialState() or getDefaultProps() methods returning objects with clashing keys.

というわけで同じkeyの値を指定するとエラーになってしまうので注意が必要です。

二重定義

同じメソッドをmixinとComponentで定義してみます。

var Mixin = {
  foo: function() {
    console.log("mixin foo");
  }
};

var Hello = React.createClass({
  mixins: [Mixin],
  foo: function() {
    console.log("component foo");
  },
  render: function() {
    return <div>hello</div>
  }
});

React.render(<Hello />, document.body);
// Uncaught Error: Invariant Violation: ReactCompositeComponentInterface: You are attempting to define `foo` on your component more than once. This conflict may be due to a mixin.

この場合はエラーになります。


mixinをうまく使うことでコードを減らすことが出来るので、わかりにくくなりすぎない程度に使っていくと便利です。

今回はmixinについて書きました。
明日は、Addonについて書きたいと思います。

koba04
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした