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

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

ただいまの
回答率

90.52%

  • React.js

    829questions

    Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

  • Redux

    112questions

reducerのfunctionを動かしたい(redux)

解決済

回答 2

投稿 編集

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

yamady

score 148

こちらの質問で、Reduxを通してエラーモーダルを表示させるための質問をしたのですが、やはり上手くいかなかったので、再度質問させていただきます。

 エラー

  onError is not found.

Reducerの中にonError()を書いていないので当たり前ではあるのですが、Reducerの中にAlert文を書くのは不整合であるように感じます。
Reducerで起こしたonError()アクションをどのようにすれば、View上のonError()を起こすのに繋がるのかが知りたいところです。

 ソースコード

actions

・・・
export const userCreate = ({ user }) => {
  return (dispatch) => {
      firebase.database().ref(`/users/`)
        .set({
          user
        })
        .then(() => {
        dispatch({ type: 'user_save_success' });
      });
    })
    .catch(err => {
       dispatch({ type: 'USER_SAVE_FAIL' });
    });
  }
}
・・・

reducer

export default (state = initialState, action) => {
  switch(action.type) {
    case 'USER_UPDATE':
      return { ...state, [action.payload.prop]: action.payload.value };
    case 'USER_SAVE_SUCCESS':
      return { initialState, successModal: true };
    case 'USER_SAVE_FAIL':
      return { ...state, failedModal: true };
    default:
      return state;
  }
};

View(UserCreate.js)

class CreditCard extends React.Component {
  state = {
    showModal: false,
    error: null
  };

  static navigationOptions = ({ navigation }) => {
    const { params = {} } = navigation.state;
    return {
      headerTitle: 'ユーザーの新規作成',
      headerLeft: (
        <TouchableOpacity
          onPress={()=> navigation.goBack()}
          style={styles.headerIcon}
        >
          <Icon name='chevron-left' size={28} style={{color: '#fff'}}/>
        </TouchableOpacity>
      ),
      headerRight: (
        <TouchableOpacity
          onPress={() => params.handleSave()}
        >
         <Text style={styles.headerBtn}>{I18n.t('save')}</Text>
        </TouchableOpacity>
      ),
      headerStyle: {
        backgroundColor: Theme.PRIMARY,
      },
      headerTitleStyle: {
        color: '#fff',
        fontWeight: 'bold'
      }
    };
  };

  onButtonPress() {
    const { firstName, lastName } = this.props;

    this.props.userCreate({ firstName, lastName });
  }

  componentDidMount() {
    this.props.navigation.setParams({ handleSave: this.onButtonPress.bind(this) });
  }

  render() {
    if(this.props.error === true) {
      Alert.alert(
        'エラーが発生しました',
        [
          {text: 'キャンセル', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
          {text: 'はい', onPress: () => this.onConfirmReport()},
        ],
        { cancelable: false }
      )
    }

    return (
      <View>
          <TextInput
            value={this.props.firstName}
            onChangeText={value => this.props.userUpdate({ prop: 'firstName', value })}
          />
          <Input
            value={this.props.lastName}
            onChangeText={value => this.props.userUpdate({ prop: 'lastName', value })}
          />
      </View>
    );
  }
}

const mapStateToProps = (state) => {
  const { firstName, lastName } = state.userForm;

  return { firstName, lastName };
};

export default connect(mapStateToProps, {
  userUpdate, userCreate
})(UserCreate);

ここでいうUserCreate.jsのonErrorを動かしたいです。
どうぞよろしくお願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+2

前回の質問の続きですね。もう少し具体的に書きます。
とはいえ、ざっくり回答ですが、ご参考までにどうぞ!

 action

export const userCreate = ({ user }) => {
    return (dispatch) => {
            // 省略
        })
        .catch(error => {
             dispatch({ 
                type: 'USER_SAVE_FAIL', 
                payload: error, 
                error: true, // オプション 
                meta: {} // オプション
             });

        });
    }
}

参考:https://github.com/redux-utilities/flux-standard-action - 「Flux Standard Action
」というaction objectの形式のスタンダードみたいなものが提唱されていて、この形式に従ってライブラリーを作るライブラリーオーサーもそれなりに多いようです。typeとpayloadは必須。errorとmetaプロパティーは任意という感じの形式ですね。

 reducer

// usersReducer.js

const initialState = {
  users: [],
  isFetching: false, //API通信中かどうか(読み込み中かどうか)
  error: null // API通信周りのerrorオブジェクトが入る
}

export default (state = initialState, action) => {
    // 省略
    // action.typeやaction.errorに応じて、stateを変える
}

参考:https://github.com/reduxjs/redux/blob/master/examples/real-world/src/reducers/index.js#L16 - リンク先コードのようにerror用のreducerを別途に用意するパターンも有り。

 component / container

//省略
// this.props.isFetchingがtrueならローディングアイコンを表示するなど
// this.props.errorがnullじゃない場合は、アラートを表示したり、通信実行のリトライボタンを表示するなど

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/29 11:27

    Hayatoさん、いつもありがとうございます!迅速なご回答で非常に助かっています!
    (理解が悪く、なんどもお手数おかけします...汗)
    Reducerからはstateの変更を送り返すことができるということですよね。別件の質問になると思うのですが、受け取ったView側でファンクションを条件によって押したり押さなかったりできる方法ってどれが正しいのでしょうか。

    if(isFetching: true) {
    ・・・
    }
    とかだとエラーになってしまうんですよね。汗

    キャンセル

  • 2018/06/29 11:30

    こんにちは!すみません、別件の質問の意味がちょっとわからないです!

    キャンセル

  • 2018/06/29 11:34

    早速ありがとうございます!
    一旦整理して再ポストします。!

    キャンセル

  • 2018/06/29 18:14

    //省略
    // this.props.isFetchingがtrueならローディングアイコンを表示するなど
    // this.props.errorがnullじゃない場合は、アラートを表示したり、通信実行のリトライボタンを表示するなど

    これって componentDidMount() { }の中に書くのが正解なのでしょうか。
    理解が悪くすみません。

    キャンセル

  • 2018/06/29 18:26

    ソースコードを更新してみたのですが、上手く通りませんでした(汗)

    キャンセル

  • 2018/06/29 20:47 編集

    ライフサイクルメソッドの中ではなく、renderメソッドの中で、ですね。(追記- ライフサイクルメソッドでも適切なライフサイクルメソッドの中であればOKですが、render内がひとまず手っ取り早いかなと)

    キャンセル

  • 2018/06/30 11:36

    ありがとうございます!
    ```
    render() {
    if(this.props.failedModal === true) {
    Alert.alert(
    'エラーが発生しました',
    [
    {text: 'キャンセル', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
    {text: 'はい', onPress: () => this.onConfirmReport()},
    ],
    { cancelable: false }
    )
    }

    console.log('&&&&&&&');
    return (
    ```
    これでやってみたのですが、reduxが通ってきたあとに機能してくれませんでした。

    キャンセル

  • 2018/06/30 13:09 編集

    「これでやってみたのですが、reduxが通ってきたあとに機能してくれませんでした。」について、具体的に説明すると、どういう状況でしょうか? 説明が難しい、または苦手な場合は、必要なコードを全部載せてもらった方が早いかもしれません。

    キャンセル

  • 2018/06/30 17:26

    ご回答いただきまして、本当にありがとうございます!
    説明が分かりづらくて申し訳ございません。
    こちら、質問欄に再度記述させていただきます(_ _)

    キャンセル

  • 2018/06/30 17:26

    ご回答いただきまして、本当にありがとうございます!
    説明が分かりづらくて申し訳ございません。
    こちら、質問欄に再度記述させていただきます(_ _)

    キャンセル

  • 2018/07/01 10:18

    追記されたコード拝見したのですが、UserCreate.js内でthis.props.errorを参照出来る理由が掲載されている限られたコードから見えてこないです。なぜ、参照出来るのですか?

    キャンセル

  • 2018/07/01 10:35

    「ここでいうUserCreate.jsのonErrorを動かしたいです。」← そもそも、onErrorなるものがもはや見当たらないです。。。

    キャンセル

  • 2018/07/01 23:16

    ありがとうございます。一旦、すべて整理し直します(_ _)

    キャンセル

  • 2018/07/03 23:10

    Hayatoさん、ありがとうございます。色々と模索した結果、本質的ではありませんが、解決することができました(_ _)

    キャンセル

  • 2018/07/04 20:25

    おー、そう解決しましたか。そうじゃない感はありますが、とりあえず前に進むことは大事ですからね、その勢いで頑張ってください!

    キャンセル

  • 2018/07/05 12:26

    Hayatoさん、いつも本当にありがとうございます!
    課題がここで解決する度にReact愛が深まっていきます!^^

    キャンセル

0

        .catch(err => {
          dispatch({ type: 'user_save_failed' });
          Alert.alert(
            '失敗しました',
            '保存に失敗してしまいました。',
            [
              {text: 'OK', onPress: () => console.log('OK Pressed')},
            ],
            { cancelable: false }
          )

本質的な解決ではありませんが、reduxの中に関数を書くことで何とかやりたいことは実現できました。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

同じタグがついた質問を見る

  • React.js

    829questions

    Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

  • Redux

    112questions