2015-12-08 15 views
6

私はReduxでアプリケーションを書いているとし、第三者のライブラリを使ってログを追加することを前提としています。次のようにそのAPIは以下のとおりです。react/reduxアプリケーションのサービスインスタンスはどこに保持されますか?

let logger = createLogger('xyz'); 
logger.log('foobar'); 

私は間違いなく、アプリケーションの初期化時に一度だけ、ロガーインスタンスを作成したい:

function createLogger(token) { 
    // the logger has internal state! 
    let logCount = 0; 

    return { 
     log(payload) { 
      logCount++;   // modify local state 

      fetch('/someapi', { // ship payload to some API 
       method: 'POST', 
       body: payload 
      }); 
     } 
    }; 
} 

は、私は、このようなライブラリーなものを使用します。しかし、問題はです。どこでロガーインスタンスを保存しますか?

最初の命令は、店のどこかに置くことです。しかしそれは良いアイデアですか?コードで説明したように、ロガーオブジェクトはステートフルで、クロージャーにカウンターを格納します。私は不変オブジェクトと同じように新しいインスタンスを取得しません。われわれが知っているように、状態は純粋な減速器の機能によってのみ変更されるべきです。

他の可能性は、reduxミドルウェアクロージャのどこかにインスタンスを作成するか、グローバル変数を作成することです。これは明らかにテスト容易性の点で悪です。

これは(私は思う)むしろ一般的なシナリオのベストプラクティスですか?

+0

ES6モジュールを使用していますか?コンポーネント 'log'は直接呼び出すか、ストア/アクションによって自動的にログ記録されますか? – Tyrsius

+0

はい、ES6モジュールを使用しています。他の質問については、私はこれらの呼びかけが自然の場であると思っています。私は自分のコンポーネントが副作用を起こさせたくない。 – VoY

+0

ロガー自体がアプリケーション自体の状態に副作用を引き起こさない場合は、おそらくミドルウェアに属している可能性があります。しかし、あなたのコードからは不明な点がいくつか残っています。 (1)トークンパラメータの目的は何ですか? (2)logCount変数の目的は何ですか? (トークンもlogCountもポストリクエストに含まれません)(3)最後に、ペイロードは何ですか?それは行動や州から派生したものか? –

答えて

2

ES6モジュールを使用しているので、使用する予定のある場所であれば、私はロガーをモジュールとしてexportimportに設定します。私は、アクションからのロギングは、コンポーネントを認識しないようにし、ストアを副作用で汚染しないため、確実な計画であると思います。

function createLogger(token) { 
    // the logger has internal state! 
    let logCount = 0; 

    return { 
     log(payload) { 
      logCount++;   // modify local state 

      fetch('/someapi', { // ship payload to some API 
       method: 'POST', 
       body: payload 
      }); 
     } 
    }; 
} 

export default const logger = createLogger('xyz'); 

あなたの行動クリエイター

import logger from 'logger-module'; 

// 
logger.log('somestuff'); 

テストはまだロガーをインポートし、あなたが傍受する必要があり、そのメソッドにどんなスパイ/スタブを配置することにより、容易に達成可能です。サードパーティのライブラリであること

/** 
* Sends crash reports as state is updated and listeners are notified. 
*/ 
const crashReporter = store => next => action => { 
    try { 
    return next(action) 
    } catch (err) { 
    console.error('Caught an exception!', err) 
    Raven.captureException(err, { 
     extra: { 
     action, 
     state: store.getState() 
     } 
    }) 
    throw err 
    } 
} 

RavenRedux documentationから

+0

だから、基本的には、ロガーを使って、実際のロガーの代わりに模擬したインポートステートメントをインポートするライブラリを利用してテストを行いますが、正しく理解できましたか? – VoY

+0

実際のロガーをインポートすることはできます。そのメソッドが使用される前にスパイ/スタブが置き換えられている限り、呼び出しは依然としてインターセプトされます。その単なるjavascriptオブジェクト、およびスパイ/スタブがそのプロパティを置き換えます。その標準的なテスト手法です。 – Tyrsius

+0

グローバル変数に似たやり方ですが、実装を比較的簡単にスワップすることができます。しかし、モジュールレベルのロガーを1つだけ取得するので、reduxアプリケーションの2つの独立したインスタンスを作成することはできません。 – VoY

0

ライブラリに独自の状態がある場合は、ミドルウェアでその状態を使用しても問題ありません(状態はライブラリであり、アプリではありません)。なんらかの理由で状態を作成している場合、その状態は、おそらくstore.loggerなどで、Reduxストアに属している必要があります。

関連する問題