简体   繁体   English

哪一个在react / redux应用程序中保存服务实例?

[英]Where does one hold service instances in a react/redux application?

Suppose I am writing an application in Redux and I am tasked to add logging using a 3rd party library. 假设我在Redux中编写应用程序,我的任务是使用第三方库添加日志记录。 Its API is as follows: 其API如下:

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
            });
        }
    };
}

I would then use the library something like this: 然后我会使用这样的库:

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

I definitely want to create the logger instance just once during application init. 我绝对想在应用程序初始化期间只创建一次logger实例。 But then the question is: where do I store the logger instance ? 但问题是: 我在哪里存储记录器实例

First instict is to put it somewhere in the store. 第一个是将它放在商店的某个地方。 But is that a good idea? 但这是个好主意吗? As I have demonstrated in the code the logger object is stateful, it stores a counter in the closure. 正如我在代码中演示的那样,logger对象是有状态的,它在闭包中存储了一个计数器。 I do not get a new instance like I would with an immutable object. 我没有像使用不可变对象那样获得新实例。 As we know, state should only be modified via pure reducer functions. 我们知道,只应通过纯缩减器函数修改状态。

Other possibilities are to create the instance somewhere in a redux middleware closure or just create a global variable, which is obviously evil in terms of testability. 其他可能性是在redux中间件闭包中的某处创建实例,或者只创建一个全局变量,这在可测试性方面显然是邪恶的。

Is there a best practice for this (I would think) rather common scenario? 是否有最佳实践(我认为)相当常见的情况?

Since you are using ES6 modules I would setup your logger as a module, export it, and import it wherever you plan to use it. 由于您使用的是ES6模块,我会将您的记录器设置为模块, exportexport ,并将其import到您计划使用它的任何位置。 I think logging from the actions is a solid plan, since it keeps the components unaware, and doesn't pollute the store with side-effects. 我认为从操作中记录是一个可靠的计划,因为它保持组件不知道,并且不会污染具有副作用的商店。

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');

Your action creators 你的动作创作者

import logger from 'logger-module';

//
logger.log('somestuff');

Testing is still easily achievable by importing the logger and placing whatever spy/stub on its methods that you need to intercept. 通过导入记录器并在其需要拦截的方法上放置任何间谍/存根,仍可轻松实现测试。

From the Redux documentation : Redux文档

/**
 * 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
  }
}

Raven being a third-party library. Raven是第三方图书馆。

If the library has its own state then it shouldn't be an issue using it in middleware (the state belongs in the library and not your app). 如果库有自己的状态,那么在中间件中使用它不应该是一个问题(状态属于库而不是你的应用程序)。 If you're creating a state for it, for some reason, then that state should belong in the Redux store, probably under store.logger or something. 如果你正在为它创建一个状态,由于某种原因,那么该状态应该属于Redux存储,可能在store.logger之下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM