0

Vue/Vuex beginner here. Is there a way to set the initial state in Vuex dynamically? I have a boolean state called is_here (true if a member is present), whose value I want to check dynamically with a conditional statement before setting.

If I try to compile the code like below, it returns this error: TS2564: Property 'is_here' has no initializer and is not definitely assigned in the constructor.

import { Action, Module, Mutation, VuexModule, getModule } from 'vuex-module-decorators';

export interface IMemberState {
  is_here: boolean;
}

@Module({dynamic: true, store, name: 'member', namespaced: true})
class Member extends VuexModule implements IMemberState {
  public is_here: boolean // The app expects me to set true or false here
}

If I set the default value for the initializer to true or false, the app compiles correctly. But if I change the status (let's say from true to false) and refresh the page, the state reverts back to true (a different button is rendered based on this boolean, so I can see it's reverted back to true).

public is_here: boolean = true

What I want to do is to make an API call and check certain things before setting the is_here state. I wrote an @Action that does the necessary checks.

@Action({})
public async setHereStatus() {
  await axios.get('api/member_status').then((response)=>
  if(response.here_status) {
  // This action returns true or false
  )
}

I tried putting this @Action instead of hardcoding the value for is_here would work, but I got this error: TS2322: Type '() => Promise<boolean>' is not assignable to type 'boolean'.

public is_here: boolean = this.setHereStatus()

How can I assign this state dynamically in this kind of scenario? Am I supposed to use something like created or mounted?


[Update] As @ittus commented, I should've used a @Mutation to set the is_here status. I've been experimenting like this.

@Module({dynamic: true, store, name: 'member', namespaced: true})
class Member extends VuexModule implements IMemberState {
  public is_here: boolean = false

  @Mutation
  public SET_HERE_STATUS(status: boolean): void {
    this.is_here = status
  }

  @Action({})
  public async setHereStatus() {
    await axios.get('api/member_status').then((response)=>
    if(response.here_status) {
      this.SET_HERE_STATUS(true)
    }else {
      this.SET_HERE_STATUS(false)
  }
}
// In the Vue component where I use this state
  created () {
    memberModule.setHereStatus()
  }

However, the same issues persist; if I refresh the page, or close the window and access the same URL again, the state is reset. I don't know if my created hook is functioning properly.

reesaspieces
  • 1,600
  • 4
  • 18
  • 47
  • `if I refresh the page, or close the window and access the same URL again, the state is reset.` -> Vuex does not persist the state automatically. If you want to keep the state over a page reload, you need to store the state periodically e.g. in the localStorage. There are plugins for that. – ssc-hrep3 Jun 17 '19 at 08:23
  • I read that in this [question](https://stackoverflow.com/questions/43027499/vuex-state-on-page-refresh?rq=1) so I was looking into it. In my case, when I configured the `created` hook correctly, the state persisted even when I refreshed or reopened the page. I'm not sure what kinds of cases necessitate the use of localStorage... is there a clear distinction? – reesaspieces Jun 17 '19 at 08:48

1 Answers1

0

You should call mutation to update vuex state.

Or you can combine mutation and action with MutationAction

@Module({dynamic: true, store, name: 'member', namespaced: true})
class Member extends VuexModule implements IMemberState {
  public is_here: false
  public is_here_loaded: false

  @MutationAction({mutate: ['is_here', 'is_here_loaded']})
  public async setHereStatus() {
    const response = await axios.get('api/member_status')
    return {
      is_here: response.here_status,
      is_here_loaded: true
    }
  }
}

You can set a default value to false. If you need to wait for variable is_here to be set, you can use an additional flag to check. In the above code, I use is_here_loaded as the flag variable.

setHereStatus should be called when component created

ittus
  • 21,730
  • 5
  • 57
  • 57
  • Thank you. Would it be possible to give an example of how to do it using a normal `@Mutation` and `@Action` instead of a `@MutationAction`? I made an update to my question because I realised I need to use `@Mutation`, but I still have the same issue. – reesaspieces Jun 17 '19 at 08:14
  • 1
    created hook should be in Vue component, not in vuex module. – ittus Jun 17 '19 at 08:35
  • Just now realised that, and fixed the code sample. It seems to be working now. Thank you! – reesaspieces Jun 17 '19 at 08:37