假设我在Redux中编写应用程序,我的任务是使用第三方库添加日志记录。其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
});
}
};
}
然后我会使用这样的库:
let logger = createLogger('xyz');
logger.log('foobar');
我绝对想在应用程序初始化期间只创建一次logger实例。但问题是:我在哪里存储记录器实例?
第一个是将它放在商店的某个地方。但这是个好主意吗?正如我在代码中演示的那样,logger对象是有状态的,它在闭包中存储了一个计数器。我没有像使用不可变对象那样获得新实例。我们知道,只应通过纯缩减器函数修改状态。
其他可能性是在redux中间件闭包中的某处创建实例,或者只是创建一个全局变量,这在可测试性方面显然是邪恶的。
这是一种最佳实践(我认为)相当常见的情况吗?
答案 0 :(得分:3)
由于您使用的是ES6模块,我会将您的记录器设置为模块export
,并将import
设置为您计划使用它的位置。我认为从动作中记录是一个可靠的计划,因为它保持组件不会发现,并且不会污染具有副作用的商店。
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');
通过导入记录器并在其需要拦截的方法上放置任何间谍/存根,仍然可以轻松实现测试。
答案 1 :(得分:0)
/**
* 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
是第三方图书馆。
如果库有自己的状态,那么在中间件中使用它不应该是一个问题(状态属于库而不是你的应用程序)。如果你正在为它创建一个状态,由于某种原因,那么该状态应该属于Redux存储,可能位于store.logger之下。