MauirceA
MauirceA

Reputation: 321

Vue: How to avoid using setTimeout in mounted() to wait for props to be available?

I find myself in a pattern of using setTimeout a lot to wait for the initial data to be loaded and available in my Vue components. Often, I'll be try to access an initial data and it won't be ready. Example:

data: {
  return() {
     name: null
  }
},
props: {
    otherName: {type: String}
},
mounted() {

     if (this.otherName == "Bob" {
        // do something
     }
}

Would this pattern work? I was thinking about this but how often would this fire? Would I be repeatedly be firing this? At least with mounted, I know it happens ONCE and only once.

computed: {
   getOtherName() {
       return this.otherName;
   }
},
watch: {
   getOtherName(newValue, oldValue) {  
       if (oldValue != null && newValue == "Bob) {
          //do something -- the prop will be null though so I use a setTimeout to wait for it to be available and not null
       }
   }
}

Upvotes: 0

Views: 1399

Answers (1)

B. Fleming
B. Fleming

Reputation: 7220

Watched properties will fire every time there is a detected change to the property, so that solution isn't quite ready. It's good that you're moving away from using timeouts, though, because those are just silly, especially since you're defeating the purpose of Vue being an MVVM framework.

If you want to have an initialization step, then you have two reasonable options:

  1. You can mount the component ahead of time and then track an initialized flag to determine whether or not you've performed that initialization step.
  2. You can defer mounting the component until your data is ready in the first place.

Option 1 will look something like this:

data() {
    return {
        initialized: false
    };
},
watch: {
    getOtherName(newValue, oldValue) {
        if(this.initialized || oldValue !== null) {
            return;
        }

        // Perform initialization logic.

        this.initialized = true;
    }
}

Option 2 will look something like this:

// HTML template
<my-component v-if="data_source !== null" :otherName="data_source"></my-component>

// JS
mounted: {
    // Perform initialization logic.
}

Upvotes: 1

Related Questions