Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. Its API is as follows:

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. 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. 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.

Is there a best practice for this (I would think) rather common scenario?

like image 852
VoY Avatar asked Dec 08 '15 20:12

VoY


People also ask

Where is state stored in Redux?

The state in Redux is stored in memory, in the Redux store. This means that, if you refresh the page, that state gets wiped out. The state in redux is just a variable that persists in memory because it is referenced (via closure) by all redux functions.

How a store is available to all the components in a Redux architecture?

The Redux store is created using the configureStore function from Redux Toolkit. configureStore requires that we pass in a reducer argument. Our application might be made up of many different features, and each of those features might have its own reducer function.

How do you store data on Redux?

It's simple to get access to the store inside a React component – no need to pass the store as a prop or import it, just use the connect function from React Redux, and supply a mapStateToProps function that pulls out the data you need. Then, inside the component, you can pass that data to a function that needs it.


1 Answers

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. 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.

like image 193
Kyeotic Avatar answered Sep 30 '22 11:09

Kyeotic