Search code examples
javascriptreact-reduxgeneratorredux-sagasuperagent

Redux saga using parameters of other instances of the class


I have four different instantiations of an API class, three of which have the same parameters, and one which has different ones. However, the class with the different parameters seems to be instantiated with the parameters of the other three instances. Why is this happening?

I have a number of generator functions (using redux-saga), where I pass in as a parameter a new instance of the API class with an id and access token.

Here's an example of one of the three similar generators:

const watchMagazineFetchRecentArticles = function* () {
  yield takeEvery(C.FETCH_RECENT_ARTICLES, fetchMagazineRecentArticles, 
  new APIClass(SPACE_ID_ONE, ACCESS_TOKEN_ONE))
}

and this is the different one:

const watchPressPageArticles = function* () {
  yield takeEvery(C.FETCH_PRESS_PAGE_ARTICLES, 
  fetchPressPageArticlesSaga, (new APIClass(SPACE_ID_TWO, 
  ACCESS_TOKEN_TWO)))
}

Here's the API class:

import prefix from 'superagent-prefix'
const agent = require('superagent-use')(require('superagent'))

export default class APIClass {
  constructor (spaceID, accessToken) {
    this.fetchRecentArticles = this.fetchRecentArticles.bind(this)
    this.fetchPressPageArticles = this.fetchPressPageArticles.bind(this)

    agent.use(prefix(`https://cdn.contentful.com/spaces/${spaceID}`))
    agent.use(((req) => {
      req.header.Authorization = `Bearer ${accessToken}`
      req.header.Accept = 'application/json'

      return req
    }))

    this.instance = agent
  }

  fetchRecentArticles (numOfArticles) {
    return this.instance
      .get(`/entries?content_type=article&select-fields&order=-fields.publishDate&limit=${numOfArticles}`)
      .then(response => response.body)
      .catch(error => console.error(error))
  }

  fetchPressPageArticles () {
    return this.instance
      .get('/entries')
      .then(response => response.body.items)
      .catch(error => console.error(error))
  }
}

When I call the watchPressPageArticles function, I can see that the api request in the network tab is being called with the SPACE_ID_ONE and ACCESS_TOKEN_ONE parameters instead of SPACE_ID_TWO and ACCESS_TOKEN_TWO.

Also worth noting that when I comment out the other functions (that use SPACE_ID_ONE and ACCESS_TOKEN_ONE), the api request is made with the correct spaceID and token.

I'm not sure why the saga is not taking in the correct arguments or how to explain this behavior. Any ideas would be appreciated!


Solution

  • It seems to the problem is not in Saga, but same agent is used in any new api instance. If you check

    const i1 = new APIClass('1', '1');
    const i2 = new APIClass('2','2');
    
    console.log(i1.instance === i2.instance); // true
    

    Possible fix is to instantiate agent in a constructor, so instead of

    const agent = require('superagent-use')(require('superagent'))

    Let's move agent instantiation into constructor:

    const superagentUse = require('superagent-use');
    const superagent = require('superagent');
    
    module.exports = class APIClass {
    constructor (spaceID, accessToken) {
        const agent = superagentUse(superagent); // this agent will be used only in this instance
        agent.use(prefix(...));
    

    Hope it helps.