Reactでobnizを使おう


Reactでobnizを使うにはちょっと一工夫いるっぽいので試してみました。

Reactで使うWebpackが、obnizで使っているwebpackを認識しなくて設定を引き継いでくれないようで、底の部分に関していくつか修正が必要なようです。

とにかく結論だけ知りたいんだという方は、こちらのgithubを参照ください。

dialog-polyfill が必要

obnizの内部ではdialog-polyfillを使っています。(nodejs版では不要ですが、HTML版にwebpackする際に必要)。

npm install で入れてしまいましょう

npm install -D dialog-polyfill

リソース読み込みのためにcssやyamlファイルを読み込めるようにする

obniz.js内部ではcssファイルやyamlファイルを扱っています。
webpackのデフォルト設定ではこれらを読み込むことができないので、
コレを読めるようにします

npm i -D json-loader yaml-loader raw-loader

webpackの設定のrulesにも、jsonやyaml、cssが読めるように設定します。

webpack.config.js

module.exports = {
  ...
  module: {
    rules: [{
      test: /\.jsx?$/,
      exclude: /(node_modules|bower_components)/,
      use: [{
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-react', '@babel/preset-env']
        }
      }]
    },
      {
        test: /\.(yml|yaml)$/,
        use: [
          {
            loader: require.resolve('json-loader'),
          },
          {
            loader: require.resolve('yaml-loader')
          },
        ],
      },
      {
        test: /\.(css)$/,
        use: 'raw-loader',
      },
    ]
  },
  ...
};

.mapエラーを消したい・・・・がまだわからず

obnizは.mapファイルをgitに入れていないため、読み込もうとしてそんなの無いよエラーが大量に出ています。
このワーニングを消したい! が解消法はわかってないです。
原因のわかっているワーニングなので、取りあえず動くし放置しましょう。

obnizとreactで使うときのサンプル

ここまでの対策でobnizは無事に動くようになります。
どんなふうにobnizとreactを使うとよいかちょっと書いてみましょう。

connectする前にはobniz.displayやobniz.switchなどのプロパティにアクセスできない

obniz.onconnectが呼ばれるまでは、obnizのプロパティは一部存在しなく、obniz.displayなどにアクセスすることはできません。

obnizにはconnectionStateというプロパティがあるので、コレを使って接続中かどうか判断します。


 if(this.props.obniz.connectionState === "connected"){
      this.props.obniz.display.clear();
      this.props.obniz.display.print(text);
 }

コールバック関数の設定タイミング

スイッチの入力などのコールバック関数の設定タイミングに注意する必要があります。

reactのDOMが作られる瞬間に、obnizがオンラインなのか未接続なのかは状況次第になります。
未接続の場合はonconnectが呼ばれた段階でコールバック関数を設定したいですが、接続済みの場合はその後onconnectが呼ばれることはないので、そこに設定しても動作しません。

そこで、ここでも接続状況教によって場合分けをする必要があります。

また、この際、obniz.onconnectを上書きすると、他のところで設定しているものが使えなくなるので、
1つしか登録できないobniz.onconnectではなく、obniz.on('connect', ()=>{ ... })を使いましょう

obniz.on('connect', ()=>{ ... })はいくつ登録しても、全部の関数が呼ばれます。

export default class ObnizSwitchState extends React.Component {
  constructor(props) {
    super();
    this.state = {switchState: "unknown"};

    if (props.obniz.connectionState === "connected") {
      this.setupObniz();
    } else {
      props.obniz.on('connect', () => {
        this.setupObniz();
      })
    }
  }

  setupObniz() {
    this.props.obniz.switch.onchange = (state) => {
      this.setState({switchState: state})
    }
  }

...

}

 というわけでサンプル

こちらのgithubに上げています。
https://github.com/9wick/obniz-react-sample

obnizIDの設定だけ変えてもらえればこんな形でうごきます。
https://github.com/9wick/obniz-react-sample/blob/master/src/js/components/Layout.js#L9