Vue component prop `undefined` when called from watcher callback

2.3k views Asked by At

I've been writing a Vue client for an instructor API for an e-learning site that fetches the associated Q&A threads for each course taught by that instructor.

The client first populates a list of courses.

Next, when a course is clicked, the ID for that course is passed to a child component as a prop called courseid, so the child component can then itself perform an API lookup to get the threads for that course using that ID.

The child component contains a method that performs the API request to get the Q&A threads called getThreads, using the prop courseid as a parameter in that request.

Finally, a watcher watches the prop courseid and calls getThreads if it changes. At least, it should.

When I click a course in the parent component's course list, the ID of that course is successfully passed to the child component as the prop courseid (the courseid prop is shown with the correct value in the Vue DevTools panel), but the browser console displays the following:

[Vue warn]: Error in callback for watcher "courseid": "ReferenceError: courseid is not defined"

Here is the content of the <script> section of the aforementioned child element:

<script>
import axios from 'axios';

export default {
  name: 'qAndAThread',
  data() {
    return {
      axiosResult: [],
      isLoading: false,
    };
  },
  props: {
    courseid:{
      default: '',
      type: String
    },
  watch: { 
    courseid: function () {
      this.getThreads();
    },
  },
  methods: {
    getThreads: function makeRequest() {
      this.isLoading = true;
      const token = '*redacted*';
      const instance = axios.create({
        baseURL: '*redacted*',
        timeout: 100000,
        headers: {
          Accept: '*/*',
          'Content-Type': 'application/json;charset=utf-8',
          Authorization: `bearer ${token}`,
        },
      });

      instance
        .get(`/courses/${courseid}/questions/?page_size=200`)
        .then((response) => {
          this.axiosResult = response.data;
          this.isLoading = false;
          this.unread = this.axiosResult.count;
        })
        .catch((error) => {
          //console.log(error);
          this.axiosResult = error;
          this.isLoading = false;
        });
    },
  },
};
</script>

Any assistance offered will be gratefully received!

1

There are 1 answers

3
mwilson On BEST ANSWER
.get(`/courses/${courseid}/questions/?page_size=200`)

should be

.get(`/courses/${this.courseid}/questions/?page_size=200`)

courseid is on your object so leaving off this will make it undefined. If you do this.courseid it should work.

I'm not up to date with how vue maintains scope, but you may also need to do this:

watch: { 
    courseid: function () {
      this.getThreads();
    },
  },

might need to be

watch: { 
    courseid: function () {
      this.getThreads.bind(this);
    },
  },