2017-05-17 17 views
0

redux-observableを使用して、react-redux-firebase側プロジェクトの自動保存を実装しています。現在、私はfirebaseデータベースへの参照(firebaseKey)を持っているFretboardコンポーネントを変更するアクションに応答するupdateFretboardEpicを持っています。 1秒間のデバウンス後、updateFretboardはコンポーネントの新しい状態をFirebaseに保存する必要があります。Redux-Observableを使用したReact-Redux-Firebaseアプリケーションでの自動保存の実装

import { 
    ADD_STRING, 
    REMOVE_STRING, 
    INC_STR_PITCH, 
    DEC_STR_PITCH, 
    ADD_FRET, 
    REMOVE_FRET, 
    UPDATE_FRETBOARD 
} from '../actions/action-types'; 

import { 
    updateFretboard 
} from '../actions/fretboard-actions'; 

export const updateFretboardEpic = (action$, store) => { 
    return action$.ofType(
     ADD_STRING, 
     REMOVE_STRING, 
     INC_STR_PITCH, 
     DEC_STR_PITCH, 
     ADD_FRET, 
     REMOVE_FRET 
    ) 
    .filter(() => store.getState().fretboard.firebaseKey !== undefined) 
    .debounceTime(1000) 
    .map(() => updateFretboard(
     store.getState().fretboard.fretboardData, 
     store.getState().fretboard.firebaseKey 
    )); 
}; 

しかし、私は現在、次のエラー取得しています:使用

export function updateFretboard(fretboardData, firebaseKey = undefined) { 
    return dispatch => { fretboards.child(firebaseKey).update(fretboardData); }; 
} 

Uncaught Error: Actions must be plain objects. Use custom middleware for async actions. 
    at Object.performAction (<anonymous>:3:2312) 
    at liftAction (<anonymous>:2:27846) 
    at dispatch (<anonymous>:2:31884) 
    at bundle.ff2509b….js:9896 
    at SafeSubscriber.dispatch [as _next] (vendor.ff2509b….js:51341) 
    at SafeSubscriber.__tryOrUnsub (bundle.ff2509b….js:392) 
    at SafeSubscriber.next (bundle.ff2509b….js:339) 
    at Subscriber._next (bundle.ff2509b….js:279) 
    at Subscriber.next (bundle.ff2509b….js:243) 
    at SwitchMapSubscriber.notifyNext (bundle.ff2509b….js:6579) 

前Reduxの-観測可能な実装には、updateFretboardは、アクションをディスパッチするReduxの-サンクを使用していましたそれはredux-observableと一緒に立つので、自動保存なしでエラーが生成されます。代わりにサンクを返すので、私はこれにそれを変更:

export function updateFretboard(fretboardData, firebaseKey = undefined) { 
    return fretboards.child(firebaseKey).update(fretboardData); 
} 

興味深いことに、updateFretboardEpicは、ストリームの最初のアクションのために自動保存エラーを返し、その後、任意の後続のアクションのために自動保存されませんでしょう。 updateFretboardは現在のところ、自分のレデューサー(Firebaseに新しい状態を渡す責任があります)を経由していませんが、将来、保存がいつ発生したのかを知り、レデューサーに渡すという約束を受けることを選択できます。

私はRxJS/redux-observableを初めて使用しているので、これを実行するより良い方法があると思われます。思考?

答えて

3

他の副作用ミドルウェア(redux-thunkなど)を使わずにredux-observableを使用すると、ディスパッチするすべてのアクションは、普通の古いJavaScriptオブジェクトでなければならないことを意味します。

updateFretboard()が返すものは明確ではありませんが、おそらくPOJOアクションではないことを除けば、それは何でもfretboards.child(firebaseKey).update(fretboardData)が返すものです。

実際にアクションを実行する代わりに、副作用として実行するだけで、その戻り値を完全に無視する場合は、do() operatorのようなものを使用します。これは、実際に次の'd値。あなたはそれをignoreElements() operatorと組み合わせて、あなたの叙事詩がこれまでに何かを放出するのを防ぐことができます。

export const updateFretboardEpic = (action$, store) => { 
    return action$.ofType(
     ADD_STRING, 
     REMOVE_STRING, 
     INC_STR_PITCH, 
     DEC_STR_PITCH, 
     ADD_FRET, 
     REMOVE_FRET 
    ) 
    .filter(() => store.getState().fretboard.firebaseKey !== undefined) 
    .debounceTime(1000) 
    .do(() => updateFretboard(
     store.getState().fretboard.fretboardData, 
     store.getState().fretboard.firebaseKey 
    )) 
    .ignoreElements(); 
}; 

(それはまだ/完全な誤りを伝播しますが)ignoreElements()を使用して、この特定の叙事詩がが何かを発することはありませんことを覚えておいてください。基本的には「読み込み専用」になります。

ignoreElements()を使用しなかった場合、あなたの叙事詩は実際に一致した同じアクションを再発し、不要な再帰を引き起こします。


保存されているものとそうでないものを逆にする方が簡単かもしれません。自動保存をトリガーするアクションのリストを維持する代わりに、あなたの叙事詩が保存することを知るために何らかの種類のプロパティを持つことができます。

// Listens for actions with `autosave: true` 
export const updateFretboardEpic = (action$, store) => { 
    return action$.filter(action => action.autosave) 
    // etc... 
}; 

// e.g. 
store.dispatch({ 
    type: ADD_STRING, 
    autosave: true 
}); 

アプリのニーズに合わせて調整します。

+0

応答ありがとうございました。 fretboards.child(firebaseKey).update(fretboardData)が返すものについて明示していないことをお詫びします。それは約束を返すので、私はそれをオブザーバブルに変え、自動アクションの成功を示すブール値で新しいアクションにマッピングしました。あなたのソリューションもうまくいきましたが、あなたが言及したように成功イベントを出すことはないでしょう。それが私が約束したルートに行った理由です。 –

1

私は自分の問題の解決策を見つけました(ジェイが正しい方向に向いてくれてありがとう!)。

私の質問では、fretboards.child(firebaseKey).update(fretboardData)が実際に何であるかについてはっきりとしていませんでした。 fretboards.child(firebaseKey)は、指定されたfirebaseキーを持つfretboardsの特定の子 への参照です(フルパスはfirebase.database().ref( 'fretboards')。child(firebaseKey))です。 Firebaseデータベースが約束ベースのAPIを利用して、その更新が約束返します。

import { fretboards } from '../firebase-config.js'; 
import Rx from 'rxjs/Rx'; 

import { 
    ADD_STRING, 
    REMOVE_STRING, 
    INC_STR_PITCH, 
    DEC_STR_PITCH, 
    ADD_FRET, 
    REMOVE_FRET, 
    AUTOSAVE_FRETBOARD 
} from '../actions/action-types'; 

function autoSaveFretboard(fretboardData, firebaseKey = undefined) { 
    let autoSaveFretboardRequest = fretboards.child(firebaseKey) 
    .update(fretboardData).then(function(result) { 
     // won't need to pass result through reducers, so return 
     // true to indicate save was successful 
     return true; 
    }, function(err) { 
     // log error and return false in case of autosave failure 
     console.log(err); 
     return false; 
    }); 
    return Rx.Observable.from(autoSaveFretboardRequest); 
} 

export const autoSaveFretboardEpic = (action$, store) => { 
    return action$.ofType(
     ADD_STRING, 
     REMOVE_STRING, 
     INC_STR_PITCH, 
     DEC_STR_PITCH, 
     ADD_FRET, 
     REMOVE_FRET 
    ) 
    .filter(() => store.getState().fretboard.firebaseKey !== undefined) 
    .debounceTime(750) 
    .mergeMap(() => autoSaveFretboard(
     store.getState().fretboard.fretboardData, 
     store.getState().fretboard.firebaseKey 
    ).map((res) => (
     { type: AUTOSAVE_FRETBOARD, success: res } 
    )) 
    ); 
}; 
:ジェイは別のポストに与えた別の答え( Use fetch instead of ajax with redux-observable)から

const updateRequest=fretboards.child(firebaseKey).update(fretboardData) 
    .then(function(result) { 
    // do something with result 
    }, function(err) { 
    // handle error 
    }); 

借入を、私は、次の解決策を考え出しました

自動保存の成功の有無に基づいて、保存が成功したことを示すブール値が返されます。この値は、私の還元剤に渡すことができる新しいアクションAUTOSAVE_FRETBOARDにマッピングされます。

ジェイは先の投稿で指摘したとおり、約束を取り消すことはできません。 FirebaseデータベースはPromiseベースのAPIとして実装されているので、私は実際にそれを回避する方法を見ていません。現時点では、私が自動保存をキャンセルしたい理由を考えることができないので、私はこの解決策に満足しています!

+0

あなたのソリューションは素晴らしいようです! – jayphelps

関連する問題