Computed property not updating when changing store state

I have read a lot of other topics regarding it but still have not got a solution.
I am trying to access a store state in my computed property and passing it as a prop to a child component. Changing that state is not triggering my computed property. It is still evaluating to the old value.
Here is my computed property. I am trying to access a property in the state through a getter.

    getRFQProjectStatus() {
      if(this.project)
       return this.$store.getters['RBViewStore/getRFQProjectStatus'](this.project.projectId);
       return undefined;
    }

I have even tried directly hardcoding the projectId instead of sending it through object, but still the same result.

My mutation:

 setProjectStatus( state, { projectId, property ='', status }){
    console.log(property);
    let project = state.projectsListView[projectId];
    project.RFQProjectData.rfqProjectStatus = status;
    var updatedRFQProj = Object.assign({}, state.projectsListView[projectId]);
    Vue.set(state.projectsListView, projectId, updatedRFQProj);
    }

My Action

updateProjectStatus(store, {projectId, property, status}) {
   store.commit("setProjectStatus", {
      projectId,
      property,
      status
    });
    console.log(store.getters.getRFQProjectStatus(projectId));

  }

Getter:

getRFQProjectStatus: state => projectId => {
    if (state.projectsListView[projectId] && state.projectsListView[projectId].RFQProjectData && state.projectsListView[projectId].RFQProjectData.rfqProjectStatus)
    return state.projectsListView[projectId].RFQProjectData.rfqProjectStatus;
    return undefined;
  }

State:

export const state = {
  projectsListView: {},
}

Printing my getter value after committing is printing the updated value. I am not sure what I am doing wrong. Any help is appreciated.

OK, firstly, a debugging tip.

When you console log an object you can tell pretty easily which properties are reactive. Vue uses getters and setters to intercept property access, so any reactive properties will be shown as ... until you click on them. There’ll also be a load of get and set stuff lurking in the console. If you don’t see any of that for a property then it isn’t reactive. Use the to figure out exactly which of the properties you’re changing are reactive and which aren’t. Log the whole state are drill down from there.

Vue.set will only help if you are adding a new property. If the property already exists then it won’t make any difference. Even if the existing property is not reactive. You have to use Vue.set when you first add the property or its too late.

So inside your mutation, using Vue.set won’t be helping. That property already exists. If it didn’t exist then the code above would explode because project would be undefined. You need to use Vue.set when the property is first added, not when you update it.

That’s my best guess for what the problem is. When you initially populate the property in state.projectsListView you aren’t doing it correctly. The code for that isn’t included.

For this line:

project.RFQProjectData.rfqProjectStatus = status;

If the property rfqProjectStatus doesn’t already exist then you should use Vue.set. If it does already exist then it’s fine as it is.

I would remove the Object.assign. There doesn’t seem any good reason to shallow copy the project here.

Thank you for the quick reply. As you mentioned, I checked the reactivity for my projectsListView state, and by the looks of it, it looks reactive.
image
I can also see the setters and getters for the property I am trying to access (rfqProjectStatus).

The whole RFQProjectData property is populated when we construct the projectsListView object for a particular project. I am adding the code snippet for reference. getRFQProjectData will return me that property data constructed, which is then added to projectsListView along with some other properties. This is called when we first fetch the data from the backend.

 if (RBData.tags && RBData.tags.RFQRequest) {
          let rfqData = await getRFQProjectData(projectId);
          if(rfqData) 
          RBData.RFQProjectData = rfqData;
        }
         await store.commit("setProjectListView", {
          projectId,
          projectData: RBData
        });

That picture is similar to what I suggested but not quite the same. I wanted you to check the whole store state. That picture seems to show just one of the project objects. My theory was that the properties of state.projectsListView are not reactive, which isn’t something I can see from that picture.

It’s also possible that the RFQProjectData property is not reactive. That isn’t something that I can tell from that picture either. Was there a ... for RFQProjectData before you expanded it? You need to check each individual property for reactivity.

I do agree that rfqProjectStatus does appear to be reactive but that alone won’t necessarily be enough. It depends whether the computed property formed a dependency on that specific property of that specific object. Based on the code for the computed property that isn’t something I can deduce. It may have bailed on one of the earlier conditionals and if they aren’t reactive it won’t trigger anything.

The bit of code I’d most want to see is the setProjectListView mutation. That’s where I currently think the problem is most likely to be.

It could also be a problem with this line:

RBData.RFQProjectData = rfqData;

I can’t tell with the limited information I have. If RBData is already reactive and it doesn’t already have a property called RFQProjectData then this line would need to use Vue.set. But if either of those things isn’t true then the line is fine as it is currently. You can figure out which assignment is to blame using the ... stuff in the console logging. Find the property that doesn’t have a ... and that’s the problem.

There’s no need to use await before a commit. Commits are synchronous, they don’t return a promise.

state.projectsListView is a reactive property. So are all the levels inside of it.
state.projectsListView
image
image

image
getters and setters for RFQProjectData are also present.

image

As far as RBData is concerned, it is a temporary variable and not a property in the state. It is used to construct the structure for our state which is then committed in our mutation.

This is my Mutation

     setProjectListView(state, { projectId, projectData }) {
      Vue.set(state.projectsListView, projectId, projectData);
     }

Here projectData is RBData that we are passing.

That all looks fine to me.

Could you put some console logging inside getRFQProjectStatus in your component? Something like this:

getRFQProjectStatus() {
  console.log('getRFQProjectStatus called')
  console.log(this.project)
  if(this.project) {
    console.log('projectId:', this.project.projectId)
    const status = this.$store.getters['RBViewStore/getRFQProjectStatus'](this.project.projectId);
    console.log(status)
    return status
  }
       
  return undefined;
}

I’d be curious about two things:

  1. What values are logged?
  2. When are they logged relative to the rest of your code? e.g. relative to the logging you already have in setProjectStatus or updateProjectStatus?

The first time when I load my page, the computed property is getting called with the getter returning the initial value of the status, that is received from the backend. At this time the mutation is not called.

But the second time when I update my status, I,e when the mutation is being called, the computed property is not triggered and hence nothing gets logged, except the console statements inside my actions/mutations.

I’m starting to run out of ideas.

I recall seeing something like this once with a Vite project. In that case the problem turned out to be a mistake in the package.json where Vue wasn’t included explicitly in the dependencies. That resulted in two separate copies of Vue being used, one by the components and the other by Vuex. If that sounds plausible then we can maybe investigate further but it’s unlikely. In that scenario you wouldn’t be able to get any state updates to appear in components reactively. It can only really occur in a new project or one that has recently changed dependencies, otherwise you’d have noticed it long ago.

If you’re able to put a cut-down version of your code somewhere I can run it then I’d be happy to take a look. Maybe JSFiddle or a GitHub project. I can probably track down the problem if I can see it for myself.

Turns out it was indeed a linking issue. When I directly replaced my file in the node modules of my application, the issue got resolved.