yucatio@システムエンジニア

趣味で作ったものいろいろ

react-redux-firebaseで、pushの自動生成key(ID)を事前に取得

firebaseでpushのkeyを事前取得

firebaseの公式サイトには、key(ID)の取得は以下のように書いてあります。

// Get a key for a new Post.
var newPostKey = firebase.database().ref().child('posts').push().key;

react-redux-firebaseでも同様に、

const firebase = getFirebase();
const id = firebase.push('path/to/data').key

でkey(ID)を取得することができます。pushの第1引数にパスを指定して、第2引数は省略します。 firebase.push(‘path/to/data’)はサーバへ通信を行わないので、オフライン時にも結果がすぐに返ってきます。

firebase.push('path/to/data').keyでkey(ID)を取得した後、firebase.set(`path/to/data/${id}`,obj)を実行することで、先に取得したkey(ID)にデータを登録することができます。

keyの事前取得は、上の公式ページのように同一キーで複数のパスに書き込む場合や、以下で示すように新規作成されたデータがサーバにコミット(データが登録)されたかどうかを表示する場合に使用します。

使用例: リストに追加(新規作成)されたデータがサーバに送信中かを表示したい

タスク管理アプリにて、 pushしたデータの送信ステータスをデータごとに表示します。 リストにタスクを追加すると、送信中を示す矢印を表示し、コミット(サーバへのデータ登録)が完了すると矢印を消去します。エラーが起こった場合は、警告マークを表示します。

動作イメージ↓

f:id:yucatio:20181114145054p:plain

action

actionの実装例です。

// reduxのaction
export const addTodo = (uid, text) => {  // uidはユーザID
  // redux-thunk
  return (dispatch, getState, {getFirebase}) => {
    const firebase = getFirebase();
    // key(id)の取得
    const id = firebase.push(`todos/${uid}`).key;

    // “送信中”の表示をする
    dispatch({type: ADD_TODO_REQUEST, todoId: id});
    // 取得したidでデータをセットする
    firebase.set(`todos/${uid}/${id}`,{
        completed: false,
        text,
    }).then(() => {
      // 表示をクリアする
      dispatch({type: ADD_TODO_SUCCESS, todoId: id});
    }).catch(err => {
      // エラーを表示する
      dispatch({type: ADD_TODO_ERROR, todoId: id, err});
    });
  }
}

reducer

reducerの実装例です。

const todoStatuses = (state = {}, action) => {
  switch (action.type) {
    case ADD_TODO_REQUEST:
      return { ...state, [action.todoId]: {status : 'sending', message: '送信中'}}
    case ADD_TODO_SUCCESS:
      return { ...state, [action.todoId]: {status : 'success'}}
    case ADD_TODO_ERROR:
      return { ...state, [action.todoId]: {status : 'error', message: 'エラーが発生しました。時間をおいて再度お試しください。'}}
    default:
      return state
  }
}

export default todoStatuses

あとは state.todoStatuses[todoId].statusの値によって表示を出し分ければ完了です。

あとがき

keyの取得方法はどうやらfirebaseのバージョンによって.key.key()のどちらを使用するか異なるので、片方でうまくいかなかったらもう片方を試してみてもよいかと思います。

redux-thunkとreact-redux-firebaseのつなぎ方は、こちらの記事を参照ください。

yucatio.hatenablog.com

バージョン

  • react-redux-firebase: 2.1.8