Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get component to wait for asynchronous data before rendering

I am calling an endpoint to bring back an object, which does fetch the data, however not fast enough for the component to grab the data and render. Instead, the component renders with blank values where there should be data.

If I break point the code on creation, then continue maybe a second later, the text correctly renders.

How do I implement it to not render until the data is back?

My API call:

checkScenarioType: function () {
    this.$http.get('ScenariosVue/GetScenarioTypeFromParticipant/' + this.ParticipantId).then(response => {
        // get body data
        this.ScenarioType = response.body.value;
        if (this.ScenarioType.timeConstraint) {
            store.commit('switchConstraint');
        }
    }, response => {
        // error callback
    });
}

The component having the issues:

var questionArea = Vue.component('questionarea', {
    props: ["scenariotype"],
    data: function () {
        return ({
            position: "",
            vehicleType: ""
        });
    },
    methods: {
        transformValuesForDisplay: function () {
            switch (this.scenariotype.perspective) {
                case 1: {
                    this.position = "Driver";
                    this.vehicleType = "Autonomous";
                    break;
                }
                case 2: {
                    this.position = "Passenger";
                    this.vehicleType = "Manually Driven";
                    break;
                }
                case 3: {
                    this.position = "Driver";
                    this.vehicleType = "Manually Driven";
                    break;
                }
            }
        }
    },
    beforeMount() {
        this.transformValuesForDisplay();
    },
    template: 
    `<h1>You are the {{ this.position }}! What should the {{ this.vehicleType }} car do?</h1>`
});
like image 887
UncountedBrute Avatar asked Mar 25 '18 14:03

UncountedBrute


People also ask

How do you wait for data before render React?

React does not wait to render.There is no way to make it wait. All is not lost, though. There's an easy fix. Components that render async data need to be prepared to render an empty state, at least once.

How do you wait until promise is resolved React?

You can use the async/await syntax or call the . then() method on a promise to wait for it to resolve. Inside of functions marked with the async keyword, you can use await to wait for the promises to resolve before continuing to the next line of the function.

How do you wait for a component to load in React?

To wait for a ReactJS component to finish updating, we use a loading state in our react application by use of the conditional rendering of the component. This can be achieved by the use of the useState and useEffect hooks in the functional components.

Can render function be async?

With Suspense, you have the ability to suspend component rendering while async data is being loaded. You can pause any state update until the data is ready, and you can add async loading to any component deep in the tree without plumbing all the props and state through your app and hoisting the logic.

Is there a way to make async render wait longer?

There is no way to make it wait. All is not lost, though. There’s an easy fix. Components that render async data need to be prepared to render an empty state, at least once. Think about what your app should look like before the data is ready. Maybe it’s empty, or maybe it’s a loading spinner, or some fancy skeleton state.

Why do I get await error when using await in render?

Error when using await in render() Why? Because asyncoperator makes the renderfunction to return a Promise, which is an object and React doesn’t know to render objects. So, how do you make React wait for your function before render?

What happens if you don't initialize a component before rendering?

Initializing state actually does run before the first render, and leaving it uninitialized is a common source of problems. This leads to errors like Cannot read property 'map' of undefined' when the component tries to render before the data is ready.

Does react wait for data to load before rendering?

React does not wait to render. Ever. React will gladly kick off an asynchronous data fetch in the background, but then it will immediately proceed with rendering – whether the data has loaded or not. (and you can be almost certain that it will not have loaded yet)


1 Answers

In cases like there's asynchronous loading of data, we typically use a simple v-if to hide the element until the data is present.

The template would be like:

<h1 v-if="position">You are the {{ position }}! What should the {{ vehicleType }} car do?</h1>

Notice the use of this in the template is unnecessary.

Also, in your case, instead of the beforeMount() hook, you would add a (deep/immediate) watch to the prop, to pick up changes when it is loaded externally:

  watch: {
    scenariotype: {
      handler: function(newValue) {
            this.transformValuesForDisplay();
      },
      deep: true,
      immediate: true
    }
  },

Full demo below.

Vue.component('questionarea', {
  props: ["scenariotype"],
  data: function () {
    return ({
      position: "",
      vehicleType: ""
    });
  },
  methods: {
    transformValuesForDisplay: function () {
      switch (this.scenariotype.perspective) {
        case 1: {
          this.position = "Driver";
          this.vehicleType = "Autonomous";
          break;
        }
        case 2: {
          this.position = "Passenger";
          this.vehicleType = "Manually Driven";
          break;
        }
        case 3: {
          this.position = "Driver";
          this.vehicleType = "Manually Driven";
          break;
        }
      }
    }
  },
  watch: {
  	scenariotype: {
      handler: function(newValue) {
    		this.transformValuesForDisplay();
      },
      deep: true,
      immediate: true
    }
  },
  template: 
  `<h1 v-if="position">You are the {{ position }}! What should the {{ vehicleType }} car do?</h1>`
});

new Vue({
  el: '#app',
  data: {
  	ScenarioType: {perspective: null}
  },
  methods: {
    checkScenarioType: function () {
      this.$http.get('https://reqres.in/api/users/2').then(response => {
        // get body data
        this.ScenarioType.perspective = response.body.data.id; // for testing purposes only
      }, response => {
        // error callback
      });
    }
  },
  mounted: function() {
    this.checkScenarioType();
  }
})
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-resource"></script>

<div id="app">
  <p>Notice while it is null, the h1 is hidden: {{ ScenarioType }}</p>
  <br>
  <questionarea :scenariotype="ScenarioType"></questionarea>
</div>
like image 169
acdcjunior Avatar answered Oct 22 '22 15:10

acdcjunior