ReactでMaterial-UIを使ってみる

インストール

$ yarn add @material-ui/core
$ yarn add @material-ui/icons

全体のテーマを整える

src/assets/theme.ts

import indigo from "@material-ui/core/colors/indigo";
import pink from "@material-ui/core/colors/pink";
import red from "@material-ui/core/colors/red";
import { createMuiTheme } from "@material-ui/core/styles";

const theme = createMuiTheme({
  palette: {
    primary: pink,
    secondary: indigo
  }
});

export default theme;

上書きできる設定は これ

src/index.tsx

import { MuiThemeProvider } from "@material-ui/core";
import theme from "./assets/theme";

ReactDOM.render(
  <MuiThemeProvider theme={theme}>
    <App />
  </MuiThemeProvider>,
  document.getElementById("root")
);

使ってみる

import Button from "@material-ui/core/Button";
import AccessAlarmIcon from "@material-ui/icons/AccessAlarm";
・・・
  <Button variant="contained" color="primary">
    <AccessAlarmIcon />
    Hello
  </Button>
・・・

color="primary"と指定して、青かったボタンが、

ピンクに表示される。

React を勉強するにあたり

今までクライアントサイドを実装のため Vue.js を勉強してきたが、仕事の関係上 React も勉強していかないと。。。

で、React でアプリケーションを実際組むのに必要そうな情報をまとめてみる。

AndroidのWebViewで、Webページ内のjavascript実行時にJSON形式の値を渡す

レイアウトにWebViewを追加。

<WebView
    android:id="@+id/webView"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:scrollbarStyle="insideOverlay"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent">
</WebView>

Java側でWebViewの取得、ひとまずアプリ内のローカルのhtmlを読み込む。

・・・
    private WebView webView;
・・・
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        webView = findViewById(R.id.webView);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setLoadWithOverviewMode(true);
        webView.getSettings().setUseWideViewPort(true);
        webView.setInitialScale(1);
        webView.loadUrl("file:///android_asset/index.html");

JSONを引数に渡して、javascriptを実行する。

        Gson gson = new Gson();
        Map<String, Object> data = new HashMap<>();
        data.put("data1", "XXXXXXX");
        data.put("data2", 10000);
        String script = "sampleFunc1(" + gson.toJson(data) + ")";
        webView.evaluateJavascript(script, null);

Alexa スキルで外部APIを使う

Alexaスキルから実行するLambda 内で外部APIを利用したい。
APIの呼び出しを非同期で行ったところ、うまくいかなかった、、、

var options = {
    uri: "https://xxxxxxx",
    headers: {
        "Content-type": "application/json",
    },
    json: {
        "data1": "xxxx",
        "data2": "yyyy"
    }
};
request.post(options, function(error, response, body){
    // this.emit(':tell', "外部API呼び出し"); // ← ここでemitを実行するとAPIコールするが、Alexaへの応答が空になる
});
// this.emit(':tell', "外部API呼び出し");  // ← ここでemitを実行するとAPIコールされず、Alexaへの応答は正常にされる

本来あるべき姿ではないと思うが、APIコールを同期的に行うことで一旦解決。

npm install sync-request

呼び出しはこんな感じ

var response = request(
    'POST',
    "https://xxxxxx",
    {
        json: {
            "data1": "xxxxx",
            "data2": "yyyy"
        }
    }
);
this.emit(':tell', "外部API呼び出し");

一応GETの場合はこんな感じ

var response = request(
    'GET',
    "https://xxxxxxx"
);
var data = JSON.parse(response.getBody('utf8'));
this.emit(':tell', "データ1は" + data.data1 + "です");

TypeScript で文字列を一文字ずつスタイルを適用する

ひとまず共通関数を定義

function decorateText(text: string, params: {[index: string]: string}[]): string {
    var result = '';
    var textArr = text.split('');
    var textLen = textArr.length;
    var paramsLen = params.length;
    for (var i = 0; i < textLen; i++) {
        var attr = '';
        let param = params[(i % paramsLen)];
        for (var key in param) {
            attr += ` ${key}="${param[key]}"`
        }
        result += `<span ${attr}>${textArr[i]}</span>`;
    }
    return result;
}

呼び出し側は

var decorateParams = [
    {"style" : "color: #000000;"},
    {"style" : "color: #ff0000;"}
];
decorateText("aaaaaaaaaa", decorateParams);

こんな感じです。