質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.98%

コールバック関数でステートが更新出来ない。

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 670

toshi_7710

score 19

前提・実現したいこと

monaca+OnsenUI+Reactで検証作業を行なっています。
その作業の内、カメラ機能を検証しています。

発生している問題・エラーメッセージ

Cordovaプラグインでカメラ起動は出来たのですが、
撮影したjpgファイルのデータをReactのstateへ更新するのに失敗します。
getPicture関数内でCordovaプラグインのnavigator.camera.getPictureを使用し、
指定した成功時のコールバック関数(関数名:onSuccess)は正常に呼び出されるのですが、
その関数内でthis.setStateがなぜか認識されていないのが原因です。

エラーメッセージ


monacaのデバッガのApp Logだと、
'Error in Scucess callbasckId:Camera62XXXXXXX: '

該当のソースコード

言語はReact.js ファイルはJsx

ここにご自身が実行したソースコードを書いてください
TestPage.jsx
/////////////////////////////////////////////
import React from 'react';
import ReactDOM from 'react-dom';
import {Toolbar, Page, Button} from 'react-onsenui';

export default class TestPage extends React.Component {

constructor(props) {
console.log("constructor");
super(props);
this.state = {
photoData: 'hoge.png' ,

}

onSuccess(imageData) {
console.log("onSuccess start-----");
// ※ 下のsetStateが認識されず、エラーになります。
this.setState({
photoData: 'data:image/jpeg;base64,' + imageData,
});
console.log("onSuccess end-----3");
}
onFail(message) {
alert("onFail");
}

// カメラ起動関数 成功時はonSuccess、失敗時はonFailが呼び出される。
getPicture() {
navigator.camera.getPicture(this.onSuccess, this.onFail, {
quality : 50,
destinationType: Camera.DestinationType.DATA_URI,
targetWidth: 100,
targetHeight: 100
});
}

render() {
return (
<Page>
<p style={{textAlign: 'center'}}>
<img src={this.state.photoData} style={{width: '70%'}} />
</p>
<p style={{textAlign: 'center'}}>
<i className="fa fa-camera fa-3x"  aria-hidden="true" onClick={this.getPicture.bind(this)}></i>
</p>
</Page>
);
}
}

試したこと

ログ出力を追加し、setState自体が認識されていないことを確認。
setState自体は正常に動くことを、別途ボタンで検証済み

補足情報(言語/FW/ツール等のバージョンなど)

より詳細な情報

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

check解決した方法

0

解決出来ました。

monacaのサンプルHello Worldのプロジェクトのソースファイルより、以下の内容で修正すると、
正常に処理が出来ました。
ありがとうございます!

・Camera.DestinationType
Camera.DestinationType.DATA_URI → Camera.DestinationType.DATA_URLに変更

・Content-Security-Policy
CordovaVer6.5に更新されたので、以下の内容に修正
"default-src * data: gap: content: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'"

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/10 18:08

    解決おめでとうございます。URI→URLとか、表記の揺れというか誤字レベルですねこれw

    キャンセル

  • 2017/08/10 18:16

    ファイルの場合は、FILE_URIと指定していたので、切り替えにDATAに変更すればいいかと思ったので、
    URIのままになっていました。
    それにしてもサポートされていない形式なら、サポートされていないことを示すエラーメッセージぐらい出て欲しいなあと思うなあ。

    キャンセル

0

Content-Security-Policydata:は許可されていますか?

<meta http-equiv="Content-Security-Policy" content="default-src *; img-src * data:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">


こういう風に、img-srcのところにdata:があれば、imgタグでdata:は使っていいよということになります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/27 17:52

    Content-Security-Policyのimg-srcの「data:」が無かったので、追記しましたが、imgのsrcには反映されないままでした。
    Content-Security-Policyは以下の内容になりました。
    <meta http-equiv=Content-Security-Policy content="default-src * data; img-src * data:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    monacaのlocal kitで開発していますので、index.htmlへの上記の設定を反映させるため、
    src/public/index.html.ejsにimgのdataの許可を追記しました。
    その後、monacaのクラウドへアップロードし、monacaのクラウドIDEのindex.htmlの上記の設定が反映されて入ることを確認しました。

    ソースファイルもES6の形式では無かったので、見直して以下、修正しました。

    import React from 'react';
    import ReactDOM from 'react-dom';
    import {Toolbar, Page, Button} from 'react-onsenui';


    export default class TestPage extends React.Component {

    constructor(props) {
    console.log("constructor");
    super(props);

    // バインド
    this._selectAlbum = this._selectAlbum.bind(this);
    this._getPicture = this._getPicture.bind(this);
    this._onSuccess = this._onSuccess.bind(this);
    this._onFail = this._onFail.bind(this);

    this.state = {
    stateKey1: 'initial value',
    photoData: './sample/' + 'hoge.png' ,
    }
    }
    _onSuccess(imageData) {
    console.log("onSuccess-----Start");
    this.setState({
    photoData:'data:image/jpeg;base64,' + imageData,
    //photoData: imageData,
    });
    console.log("onSuccess-----End");
    }
    _onFail(message) {
    console.log("_onFail");
    }

    _getPicture() {
    navigator.camera.getPicture(this._onSuccess, this._onFail, {
    quality : 80,
    destinationType: Camera.DestinationType.DATA_URI,
    //destinationType: Camera.DestinationType.FILE_URI,
    targetWidth: 100,
    targetHeight: 100
    });
    }
    _selectAlbum() {
    navigator.camera.getPicture(this._onSuccess, this._onFail, {
    quality : 80,
    destinationType: Camera.DestinationType.DATA_URI,
    //destinationType: Camera.DestinationType.FILE_URI,
    targetWidth: 100,
    targetHeight: 100,
    sourceType: navigator.camera.PictureSourceType.SAVEDPHOTOALBUM
    });
    }


    render() {

    let hoge = "Shall We Test2-1";
    console.log("render start");
    console.log(this.props.name);

    return (
    <Page>
    <div className="center">
    <p style={{textAlign: 'center'}}>{hoge}</p>
    <p style={{textAlign: 'center'}}>{this.props.name}</p>
    </div>
    <p style={{textAlign: 'center'}}>
    <img src={this.state.photoData} style={{width: '45%'}} />
    </p>
    <div className="center">
    <p style={{textAlign: 'center'}}>{this.state.photoData}</p>
    </div>
    <div className="center">
    <p style={{textAlign: 'center'}}>{this.state.stateKey1}</p>
    </div>
    <p style={{textAlign: 'center'}}>
    <i className="fa fa-picture-o fa-3x" aria-hidden="true" onClick={this._selectAlbum}>写真から選択</i>
    <i className="fa fa-camera fa-3x" aria-hidden="true" onClick={this._getPicture}></i>
    {console.log("render end")}
    </p>
    </Page>
    );
    }
    }

    見直したソースで、monacaクラウドにアップロードし、iPhoneの端末のmonacaデバッガで動作を確認すると、前回のエラーメッセージは出力されなくなり、正常に_onSuccessは終了したのですが、
    imgタグに画像が表示されない状態になりました。

    imgタグのdataとは関係ないですが、_getPicture、_onSuccessのCordovaのオプション引数を
    Camera.DestinationType.FILE_URIに切り替えた場合は、前回も最初に質問した状態のステートが認識されないエラーメッセージが出ましたが、今回ES6に見直して修正したソースだと、
    問題なく画像表示されるようになりました。

    キャンセル

0

<meta http-equiv=Content-Security-Policy content="default-src * data; img-src * data:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">


これがやっぱり気になりますね。

<meta http-equiv="Content-Security-Policy" content="default-src * data:; img-src * data:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">

こうしてみてください。Content-Security-Policyをダブルクォーテーションで囲んだ(これは念のためレベルです)のと、default-srcのところ、data:となってるべきところがdataだったので修正してみました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/28 17:44

    試してみましたが、動作は変わりませんでした。

    「default-src * data:」→「default-src * data:;」に修正し、
    Content-Security-Policyをダブルクォーテーションで囲んでmonacaのクラウドへアップロードを行うと、
    なぜかダブルクォーテーションが無くなります。
    アップロード後、直接、クラウドIDEでダブルクォーテーションを囲みましたが、動きは変わりませんでした。
     monacaデバッガにもエラーメッセージは表示されませんでした。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.98%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる