0

I have an application that needs to be authenticated with an API service before I can make any subsequent calls.

So, when the <Login/> page loads, I call the authApp() action from a useEffect hook. Once the call succeeds, I get a token in the response body and save it in my store.

Here is my authApp store:

class authApp {
    applicationToken = '' 

    constructor() {
        makeObservable(this, {
            applicationToken: observable,
            authApp: action,
            setAppToken: action
        })
    }

    setAppToken = applicationToken => {
        this.applicationToken = applicationToken
    }

    authApp = async () => {
        const apiRes = await apiAuth()
        
        if (apiRes.ok){
            const apiData = await apiRes.text()
            this.setAppToken(JSON.parse(apiData)[0].token)
        }
        else{
            //log error
        }
    }
}

The next step is to get the applications settings from the API. This call only takes the token mentioned above as an argument.

Additionally, the action to get the settings is located in a different store and, the call is made from a <Login/>'s page child component.

Here is the code for the second store:

class AppSettings {
    appSetting = {}
    applicationToken = authApp.applicationToken

    constructor() {
        makeObservable(this, {
            appSetting : observable,
            applicationToken: observable,
            getTermsAndConditions: action,
            setIsAppAuthFail: action
        })
    }
 
    getTermsAndConditions = async () => {

        const appSettingsRes = await getAppSettings(this.applicationToken)
  
        if (appSettingsRes.ok){
            const appSettingData = await appSettingsRes.text()
            console.log(appSettingData)
        }else{
            //log error
        }
    }
}

In the front-end, the <Login/> and its childs are wrapped in a observer HoC.

Here is the <Login/> child component code:

const TermAndCoditions = observer(() => {

  useEffect(() => {
    const termsAndConditions = async () => {
      const response = await AppSettings.getTermsAndConditions()
    }
    termsAndConditions()
  }, [])
  return (
      <div>{AppSettings.appSetting.text}</div>
  )
})

The problem
When the AppSettings.getTermsAndConditions() is called from the <TermAndCoditions/> component, the applicationToken value in the authApp store it empty.

What am I doing wrong? and, Is this the correct approach?

aadlc
  • 735
  • 1
  • 12
  • 26

2 Answers2

0

When you assign this applicationToken = authApp.applicationToken it basically turns into this under the hood applicationToken = '', because authApp.applicationToken is a primitive value and an empty string (I guess) when the application starts.

So, first of all you can just reference authApp in getTermsAndConditions function directly: const appSettingsRes = await getAppSettings(authApp.applicationToken)

But if you don't want to break abstraction or whatever, you can make AppSettings.applicationToken a computed value and then it will be "reactive". Like that:

class AppSettings {
    appSetting = {}

    get applicationToken() {
        return authApp.applicationToken
    }

    constructor() {
        makeObservable(this, {
            appSetting : observable,
            applicationToken: computed,
            getTermsAndConditions: action,
            setIsAppAuthFail: action
        })
    }

    // ...
 }
Danila
  • 15,606
  • 2
  • 35
  • 67
  • Thank you @Danila but, this did not work for me. Perhaps I am missing something. – aadlc Jan 31 '22 at 23:34
  • Didn't work it what way? What do you get if you log `authApp` in `getTermsAndConditions`? – Danila Jan 31 '22 at 23:39
  • It pointed me in the right direction but, I was still getting an empty string when I tried calling the second API. – aadlc Jan 31 '22 at 23:45
0

Here is how i solved it:

I added a reaction autorun() inside the useEffect() hook like so:

 useEffect(() => {
    autorun(() => {
      if (authApp.applicationToken !== '') {
        AppSettings.getTermsAndConditions(authApp.applicationToken)
      }
    })
  }, [])
aadlc
  • 735
  • 1
  • 12
  • 26