カテゴリーアーカイブ JavaScript

asaba 著者:asaba

【cordova-react】初期値がundefinedで警告受けた話

componentDidMount()内で値を受け取る処理の途中でWarning: `value` prop on `input` should not be null.という警告を

もらいました。これは、value内の値はnullで受け取ってはいけません、必ず空の状態で設定してください。

という意味になります。

componentDidmount()は、マウントされる際に一回だけ実行されます。筆者は前ページに戻った時に値を受け取る処理を作ったのですが

本来ならば空の状態でrenderされるにも関わらずその時に前ページから判別不能な値nullを既に受け取った状態で

コンポーネントを生成したので警告を受けたのだと思われます。

  componentDidMount() {
    // 前ページから受け取った値をsetStateしている
    const getName = window.localStorage.getItem('nameKey');
    
    this.setState({name: getName});

}

下のコンストラクタでnameを初期化していましたが、さきほどの関数内で先行してnullの値をsetStateしてしまっているので

これでは怒られる訳ですね・・・

 


constructor(props) {
    super(props);
    // 画面初期表示時の状態(state)を読み込む為のキャンセル可能なプロミス(Promise)を初期化する
this.state = {
      name: '',
    }
}

どうしてもコードを変えずに回避したい場合はinputタグ内でvalue = {this.state.name || ”}と書けば解決できます。

 

 名前<input type = "text" value = {this.state.name || ''} onChange = {this.handleNameCodeChange}></input>

参考にさせていただいたサイト→https://github.com/mozilla-services/react-jsonschema-form/issues/336

  • この記事いいね! (0)
村上 著者:村上

【React】onClickが呼び出されたときに任意の値の引数を渡す

React の書き方に未だに慣れていないところがあるので、まとめ。
今回は、onClick で呼び出した関数に、任意の引数を渡す方法です。

参考にさせていただいた記事はこちらから。

【React】イベントハンドラで引数を使いたい【備忘録】 – Qiita
https://qiita.com/tsuuuuu_san/items/73747c8b6e6e28f6bd23

 

上記の記事内でも書かれていますが、Reactの場合、下記のように書いても動きません。

sample(num) {
    // 行いたい処理
}

render() {
    return (
        <div>
            <button onClick={this.sample(100)}>ボタン</button>
        </div>
    );
}

記事によると、引数は渡せたものの、画面描画のたびに押していないはずのボタンの関数が実行されたとのことです。

で、解決策としては、下記のような書き方があるとのこと。
一つ目がこちら。

<button onClick={ () => this.sample(100) }>ボタン</button>

しかし、上記の方法だと、描画のたびに関数を作成することになるため、あまり良くない書き方だそうです。

二つ目がこちら。

<button onClick={ this.sample.bind(this, 100) }>ボタン</button>

何故動くのかは分かりませんが、とにかく動きました、とのこと。
引数が一つであればすっきりとしているので、個人的には好きな書き方ですね。
ですが、やはり何故動くかわからないものを使うのは少々怖いので、使用は見合わせかな。

三つ目がこちら。

sample(e) {
    console.log(e.currentTarget.getAttribute('data-num'));  // 100
}

render() {
    return (
        <div>
            <button onClick={this.sample} data-num="100">ボタン</button>
        </div>
    );
}

こちらでは、HTML5 から導入された、カスタムデータ属性を使用しています。
これは無理矢理感がなくて一番きれいかな、と思いますね。
ということで、今後は3番目のカスタムデータ属性を利用しようと思います。

 

以上、Reactで関数に引数を渡す方法でした。
と言うか、いい加減にReactの書き方に慣れたい…。頑張ります。

  • この記事いいね! (0)
asaba 著者:asaba

【cordova-react】値を動的に次ページに渡す方法

axiosなどの非同期通信を絡めた開発をしているとどうしても単純な画面遷移のことを忘れそうになってしまいます。

ただ単純に遷移だけするならば this.props.history.push({pathname: ‘/next’)}でいけますが、値をもって遷移だと始めたばかりの方は

?となってしまいがちですよね。基礎中の基礎なのでネットにもたくさん情報がありますが、コードには個人差があるのでどうしても

どれを参考にしたらいいか分からない、長くて知らない文法も書かれているから今の自分には理解し難いなど頭を抱えてしまうことも

多いと思います。自分も辛酸を嘗めてきた身ですので、ここでは可能な限り簡潔に書きまとめて同じ悩みを抱えてる方の助けに

なればいいなと思っています。分かりにくかったらごめんなさい。

 

とりあえず値をもって遷移させるコードがこちらです。↓


main.js

this.props.history.push({pathname: '/next', state: { name: this.state.name }});

 

現在の値であるstateを引数にして飛ばしています。これだけで次のページで値nameを扱うことができます。

 

めっちゃ簡単ですね。明解ですね。じゃあ次のページではどうやって受け取るの?ってなった時はこちら↓


next.js
constructor(props) {
    super(props);
    this.state = {
      name: this.props.location.state.name,
    }
}

this.props.location.state.nameとは、タグに格納されたname(値を)意味しています。つまり、前ページでタグで受け取った

値nameをthis.stateのnameキーに値として登録しています。

コンストラクタ内でconsole.log(prop)すると、locationタグの中にしっかりとnameの値が入っており

これで取ってきているのが確認できます。

これでnext.js内のrender(){}内で

{this.state.name}

と定義すればnameの値を表示させることができます。

ざっくりでしたがどうでしょうか。これがすらすら書けるようになれば初級者も卒業できて次のタスクも見えてくると思います。

  • この記事いいね! (0)
村上 著者:村上

【Cordova】端末内のファイルを開く「cordova-plugin-file-opener2」をiOSでも使う

先日投稿した、「cordova-plugin-file-opener2」を使って端末内のファイルを開く方法の、iOSバージョンです。
思ったよりも簡単に実装できました。

プラグインはこちらからご確認ください。

GitHub – pwlin/cordova-plugin-file-opener2: A File Opener Plugin for Cordova
https://github.com/pwlin/cordova-plugin-file-opener2

ちなみに先日の投稿についてはこちらから。

【Cordova】端末内のファイルを開くプラグイン「cordova-plugin-file-opener2」
https://cpoint-lab.co.jp/article/201812/【cordova】端末内のファイルを開くプラグイン「cordova-plugin-file-op/

 

さて、実装方法ですが、コード自体は下記のとおりです。

let filePath = [開きたいファイルのパス];
if (window.device.platform === 'Android') {
  filePath = filePath.replace(/^file:\/\//, '');
}
window.cordova.plugins.fileOpener2.open(
  filePath,
  'image/png',
  {
    error: function() {
      // エラー時の処理
    },
    success: function() {
      // 成功時の処理
    },
  }
);

異なる点は開きたいファイルを指定しているパス値のみで、それ以外は先日に投稿したコードとほぼ同じです。

Android と iOS では開くファイルのパス指定方法が異なるので、まずは端末が Android なのか iOS なのかを判断します。
上記のコードでは、3行目にあたります。
使用しているプラグインは「cordova-plugin-device」です。

GitHub – apache/cordova-plugin-device: Apache Cordova Plugin device
https://github.com/apache/cordova-plugin-device

device.platform で、Android や iOS などの、プラットフォームを示す文字列が取得できるので、それを使って判断しています。
で、Androdだったら、文頭についている file:// をとり、iOS だったらそのままです。

あとは、取得・整形したファイルパスとファイルのMIMEタイプを fileOpener2 のプラグインで指定して、ファイルを開く処理を実行します。
そうすれば、指定したファイルが展開されるはずです。

 

以上、iOSで端末に保存されたファイルを開く方法でした。
Androidは、サンプルコードから文頭の file:// が不要ということが分かったのですが、iOSの指定方法が見つけられず…。
で、試しに取得したファイルパスを加工せず、そのまま指定したところ、問題なく実行されたという次第です。
行き当たりばったりな気もしますが、動いたので問題なし!ということにします。

ということで、Android・iOSの両端末でのファイル展開機能の実装については、これで対応が完了です。

  • この記事いいね! (0)
村上 著者:村上

【Cordova】端末内のファイルを開くプラグイン「cordova-plugin-file-opener2」

前回、端末に画像や音声ファイルをAndroidなどの端末にダウンロードするプラグインを紹介したので、今回は端末内のファイルを開く方法について。
使用したプラグインは「cordova-plugin-file-opener2」です。

GitHubは下記からご確認ください。

GitHub – pwlin/cordova-plugin-file-opener2: A File Opener Plugin for Cordova
https://github.com/pwlin/cordova-plugin-file-opener2

 

プラグインの導入は、例のごとく下記のコマンドを実行します。

cordova plugin add cordova-plugin-file-opener2

使い方はとても簡単で、下記のように開きたい端末内のファイルのパスと、その MIMEタイプを指定するだけ。

cordova.plugins.fileOpener2.open(
    [開きたいファイルのパス], 
    [ファイルのMIMEタイプ], 
    {
        error : function(){
            // ファイル展開 失敗時に実行する処理
        }, 
        success : function(){
            // ファイル展開 成功時に実行する処理
        } 
    } 
);

ファイルのパスは、/storage/emulated/0/Pictures/[ファイル名].jpg のような感じで指定します。
こちらのパスの値については、私の環境では、ファイルダウンロードに成功した時に取得できる file:///storage/emulated/0/Pictures/[ファイル名].jpg から、file:// を取ったものを使っています。

ご覧の方の環境に合うかは分かりませんが、参考にコードを記載しておきます。

window.document.addEventListener('DOWNLOADER_downloadSuccess', function(event) {
  const data = event.data;
  const filePath = data[0].nativeURL.replace(/^file:\/\//, '');

  if (fileMIMEType !== null) {
    window.cordova.plugins.fileOpener2.open(
      filePath,
      'image/png',
      {
        error: function() {
          // ファイル展開失敗時の処理
        },
        success: function() {
          // ファイル展開成功時の処理
        },
      }
    );
  }
});

こちらはとりあえずAndroidで動作するようにしてあるだけなので、iOS には対応していません。これからやります。
なお、MIMEタイプについても、とりあえず png 形式のみ対応なので、もし扱うファイル種類が定義されていない場合は、拡張子で jpg、gif くらいは判断できるようにしたほうが良さそう。

ちなみに、動作確認中に、うっかり音楽ファイル(mp3)を imgae/png で開いてしまいましたが、エラーにはならず、ファイルが壊れているような表示になりました。
その後、きちんと audio/mp3 にしたら、開くアプリの選択肢が表示され、再生もできるようでしたので、音声ファイルも問題なさそうです。

 

以上、Android端末内のファイルをアプリで開く方法でした。
とりあえず、Androidに問題がなかったので、iOS でも使えるように修正していきたいと思います。

  • この記事いいね! (0)
村上 著者:村上

【Cordova】端末にファイルをダウンロードするプラグイン「cordova-plugin-file-downloader」【解決済】

昨日投稿した、「cordova-plugin-file-downloader」について、問題なく動作させることができたので…というか、ダウンロードできていたことが分かったので、それのご報告です。

昨日の記事はこちらから。

【Cordova】端末にファイルを保存するプラグイン「cordova-plugin-file-downloader」【未動作】
https://cpoint-lab.co.jp/article/201811/【cordova】端末にファイルを保存するプラグイン「cordova-plugi/

 

ダウンロードしたファイルの確認方法ですが、私の端末(Android 7.0)では「ダウンロード」アプリから確認ができました。
まず、アプリ一覧から「ダウンロード」アプリを開き、サイドメニューから、端末のローカルストレージを選択します。
画面イメージは下記のとおりです。

ローカルストレージを選択すると、フォルダ一覧が表示されるので、ここからプラグインの初期設定時に folder で指定したフォルダ名を探します。
無事見つかれば、このフォルダ内にダウンロードしたファイルが保存されているはずです。

ちなみに、そのコードはこちら。

downloader.init({folder: "[端末の保存先ファイル名]"});

ということで、ただ単に私がダウンロードが完了したファイルを探せなかっただけでした!
大変失礼致しました…!

 

さてしょうもない結末だったので、ダウンロード後の処理を記述する方法についてご紹介したいと思います。
オプションに onSuccess とかの指定ができなかったので、てっきり出来ないかとも思いましたが、ちゃんとありました!
コードは下記のとおりです。

document.addEventListener('DOWNLOADER_downloadSuccess', function(event) {
  const data = event.data;
  console.log(data[0].name);
  console.log(data[0].fullPath);
  console.log(data[0].nativeURL);
});

document.addEventListener の第一引数で、DOWNLOADER_downloadSuccess を指定すると、ファイルのダウンロードに成功した時にこの関数が呼び出されます。
で、変数 event に、データが入っているので、上記のように指定すると、ファイル名や保存先のパスなどが取得できます。

第一引数は、他にも DOWNLOADER_downloadErrorDOWNLOADER_downloadProgress なんかもあるので、ご要望に合わせて使い分けてください。

 

以上、cordova-plugin-file-downloader を使ったダウンロード方法とダウンロードしたファイルの確認方法でした。

  • この記事いいね! (0)
asaba 著者:asaba

【cordova-react】エラー備忘録:propTypeの型を間違えた

コンポーネントのpropの値を渡すときはpropTypeパッケージを使いますが、proptypeの方の指定を間違えるとエラー(Warning: Failed

propType: Invalid prop of type `array`)で怒られてしまいます。これはjsonで受け取る時の型が定義した型と違う時に起きるエラーです。

例えばですが[]javascript]

"point": [
{
"math": 1,
"math": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
},

jsonファイルを見ると、上のmathはkeyと値で定義しただけなので下のように定義をします。



itemKeys: PropTypes.string.isRequired

ところが下のmathは、配列で値を囲んでおり、これをproptypes.stringで定義してしまうと型が違うよと怒られてしまう訳ですね~。

配列の時は下記のように定義して上げましょう。


itemKeys: PropTypes.array.isRequired

stringのところがarrayに変わっただけなので 形式はあまり変わらないです。日本語の記事が少なかったのでもし同じエラーで悩んでいる

かたがいたら参考にしてみてください。

参考URL->https://stackoverflow.com/questions/37063418/warning-failed-proptype-invalid-prop-of-type-array-expected-object-with-re

  • この記事いいね! (0)
村上 著者:村上

【Cordova】端末にファイルを保存するプラグイン「cordova-plugin-file-downloader」【未動作】

Cordovaアプリにて画面にダウンロードボタンを配置し、それをタップしたら、あらかじめ指定しておいた画像ファイルをダウンロードする、という処理を行いたいのですが…現在、絶賛苦戦中です。
今回使用しているプラグインは「cordova-plugin-file-downloader」です。
コードがとてもシンプルで簡単だったので、指定ミスはないはずなのですが…。
エラーが発生しない、私の苦手なパターンにハマっています。

公式ページはこちらから。

GitHub – mramonlopez/cordova-plugin-file-downloader: Phonegap plugin to download a list of files or a single file to the phone, check consistency and unzip if necessary (Android and ios)
https://github.com/mramonlopez/cordova-plugin-file-downloader

cordova-plugin-file-downloader – npm
https://www.npmjs.com/package/cordova-plugin-file-downloader

 

プラグインの導入時は、下記のコマンドを実行します。

cordova plugin add cordova-plugin-file-downloader

もっともシンプルな実装方法は下記のとおりです。

downloader.init({folder: "[端末の保存先ファイル名]"});
downloader.get("[保存したいファイルのパス]");

1行目の初期化については、オプションがいくつかありますが、folder については必須事項なので、必ず指定してください。
例えばアプリ名などの文字列を指定すればよいかと。
他にも、zipファイルをダウンロードした際に、ダウンロード完了後に解凍する unzip や、展開後の zip ファイルを削除する delete オプションもあります。
また、wifiOnly という、Wi-Fiに接続されているときのみダウンロードを行うというオプションもあります。
なお、これはデフォルト値が true なので、あえて指定する必要はなさそうです。

 

プログラムとしては以上なので、こちらを実行すれば動作するはずが…何故かダウンロードできず。
ログには、download [ダウンロードしたファイルのパス] to [端末に保存したファイルのパス] とか、Saved file: [端末に保存したファイルのパス] というメッセージがあったので、ダウンロードできているようにも見えたのですが、いくら探してもダウンロードした画像が見つかりませんでした。
なおインストール時に、下記を config.xml の タグ内に追加しろとあったので、それについては対応しました。

<preference name="AndroidPersistentFileLocation" value="Compatibility" />

こちらのコードの意味は、以前の設定(Compatibility)をそのまま使用してファイルの保存するという意味になるとのこと。
value は Internal という値を指定することも可能で、こちらでは内部の保存場所を使用します。

 

幸い、若干の時間的猶予はあるので、引き続き調査したいと思います。
もしくは、違うプラグインを使うことを検討してもいいかもしれませんね。

  • この記事いいね! (0)
asaba 著者:asaba

【javaScript】readDataURLのエラー解決備忘録

inputタグで’file’と設定すると、ギャラリーから画像を選択してそれをimgタグに紐付けてあげれば選択した画像をアップロードすることが

できますが、ギャラリーから画像を選んでいてそれをキャンセルした時にエラーが起きました。アプリの機能面では影響がなかったもの

のメンテナンスの時にこのままでは可読性が下がるし追加した機能がバグを起こすかもしれないと思ったので修正を試みました。

画像はnpm startで起動したものです。

Filereaderで読み取った値がblobでなかったので実行できませんでしたという訳でしょうか。画像を選ばなかった時のreadDataURLの

進路先が用意されていなかったために起きたのだと思われます。とりあえずifで分岐点を作ってあげて、falseの時はreturnで処理を終える

宣言を用意してあげることで解決させることができました。めでたしめでたしです。

 

<pre>    if (file) {
      fr.readAsDataURL(file);
    } else {
      return;
    }
</pre>

 

  • この記事いいね! (0)
著者:杉浦

ESLintのJSDoc用プラグインeslint-plugin-jsdoc

End-of-Life for Built-in JSDoc Support in ESLint – ESLint – Pluggable JavaScript linter
 ESLintはJavaScriptの詳細で厳密なチェックをし、簡単なものによっては修正も行ってくれる検証ツールです。JSDocは次の様なJavaScript中のコメントのテンプレートです。

    /**
     * 現在のソートの状態からアイコンを表示するべきかを判断する
     * @param {String} column カラム名
     * @param {String} ascOrDesc 昇順か降順か
     * @return {Boolean} アイコンを表示するべきならtrue
     */
    shouldDisplayIcon: function(column, ascOrDesc) {

 JSDocは読みやすいことの他にもIDE等ソースコードを対象としたアプリ―ケーションで利用でき便利です。ESLintもJSDocを素でサポートしていたのですが、ESLintとJSDocの発展とメンテナ(スタッフみたいなもの)の規模の関係からJSDocのサポートが打ち切られました。これに従って、既存のJSDoc用ルールが非推奨ルールになりました。ESLintが勧めるJSDoc関連ルールを設定できる移行先プラグインがeslint-plugin-jsdocです。
eslint-plugin-jsdoc – npm
 eslint-plugin-jsdocはESLint本体よりもJSDocに詳細なルールが用意されており、より厳密なルールによってJSDocを検証できます。readmeに載っていませんがrecommendedによるルールのプリセットも用意されています。次の様に.eslintrc.jsonに記述してサクッと使えます。

  "plugins": [
    "jsdoc"
  ],
  "extends": [
    "plugin:jsdoc/recommended",
  ],
  • この記事いいね! (1)