title: React Apollo: Uncaught (in promise) TypeError: Cannot read property 'refetch' of undefined
body: <p>I have a function that has a bit of a promise chain going on, but that's besides the point.</p>
  
  <p>When I run a certain mutation's <code>refetch</code>, it gives me <code>Uncaught (in promise) TypeError: Cannot read property 'refetch' of undefined</code>.</p>
  
  <p>The strange part is that if I remove a mutation before it, it will work. So here's the code:</p>
  
  <pre class="lang-js prettyprint-override"><code>Promise.all(this.props.questionnaireData.map(({ kind, id }): Promise&lt;any&gt; =&gt; {
      const responses = this.props.formData[kind];
      return this.props.updateQuestionnaire(id, responses);
  })).then(() =&gt; {
      this.props.finishAssessment(this.props.assessmentId)
          .then(() =&gt; {
              track('Assessment -- Finished', {
                  'Assessment Kind' : this.props.assessmentKind,
                  'Assessment Id'   : this.props.assessmentId,
              });
              if (this.props.assessmentKind === 'INITIAL_ASSESSMENT') {
                  this.props.getCompletedInitialAssessment.refetch().then(() =&gt; {
                      Router.replace(routes.LoadingAssessmentResults.to, routes.LoadingAssessmentResults.as);
                  });
  
                  this.submitEmailNotifications();
              } else if(this.props.assessmentKind === 'GOAL_CHECK_IN') {
                  Router.replace(routes.MemberProgressDashboard.to, routes.MemberProgressDashboard.as);
              } else {
                  Router.replace(routes.MemberDashboard.to, routes.MemberDashboard.as);
              }
          });
  });
  </code></pre>
  
  <p>The error happens at <code>this.props.getCompletedInitialAssessment.refetch()</code>, to which I don't know why. However, when I remove <code>this.props.finishAssessment(this.props.assessmentId)</code>, only then the refetch will work.</p>
  
  <p>Basically:</p>
  
  <pre class="lang-js prettyprint-override"><code>Promise.all(this.props.questionnaireData.map(({ kind, id }): Promise&lt;any&gt; =&gt; {
      const responses = this.props.formData[kind];
      return this.props.updateQuestionnaire(id, responses);
  })).then(() =&gt; {
          track('Assessment -- Finished', {
              'Assessment Kind' : this.props.assessmentKind,
              'Assessment Id'   : this.props.assessmentId,
          });
          if (this.props.assessmentKind === 'INITIAL_ASSESSMENT') {
              this.props.getCompletedInitialAssessment.refetch().then(() =&gt; {
              Router.replace(routes.LoadingAssessmentResults.to, routes.LoadingAssessmentResults.as);
              });
  
              this.submitEmailNotifications();
          } else if(this.props.assessmentKind === 'GOAL_CHECK_IN') {
              Router.replace(routes.MemberProgressDashboard.to, routes.MemberProgressDashboard.as);
          } else {
              Router.replace(routes.MemberDashboard.to, routes.MemberDashboard.as);
          }
  });
  </code></pre>
  
  <p>will make refetch work. Otherwise it complains that it doesn't know what refetch is.</p>
  
  <p>For Apollo, I'm using the graphql HOC, and it looks like this: </p>
  
  <pre class="lang-js prettyprint-override"><code>graphql(getCompletedInitialAssessment, {
      name    : 'getCompletedInitialAssessment',
      options : { variables: { status: ['Finished'], limit: 1 } },
  }),
  graphql(updateQuestionnaire, {
      props: ({ mutate }) =&gt; ({
          updateQuestionnaire: (id, responses) =&gt; {
              let normalized = {};
  
                  for (let res in responses) {
                      let num = +responses[res];
                      // If the value is a stringified numuber, turn it into a num
                      // otherwise, keep it a string.
                      normalized[res] = Number.isNaN(num) ? responses[res] : num;
                  }
  
                  const input = {
                      id,
                      patch: { responses: JSON.stringify(normalized) },
                  };
  
                  return mutate({
                      variables: { input },
                  });
              },
          }),
      }),
  graphql(finishAssessment, {
      props: ({ mutate }) =&gt; ({
          finishAssessment: (id) =&gt; {
              const input = { id };
  
              return mutate({
                  variables      : { input },
                  refetchQueries : ['getMemberInfo'],
              });
          },
      }),
  }),
  </code></pre>
  
  <p>What I've tried is even rewriting this to use async/await, but the problem still happens:</p>
  
  <pre class="lang-js prettyprint-override"><code>try {
      await Promise.all(this.props.questionnaireData.map(({ kind, id }): Promise&lt;any&gt; =&gt; {
          const responses = this.props.formData[kind];
          return this.props.updateQuestionnaire(id, responses);
      }));
      const finishAssessmentRes = await this.props.finishAssessment(this.props.assessmentId);
      console.log(finishAssessmentRes)
  
      if (this.props.assessmentKind === 'INITIAL_ASSESSMENT') {
          const res = await this.props.getCompletedInitialAssessment.refetch();
          console.log(res);
          this.submitEmailNotifications();
          Router.replace(routes.LoadingAssessmentResults.to, routes.LoadingAssessmentResults.as);
      } else if(this.props.assessmentKind === 'GOAL_CHECK_IN') {
          Router.replace(routes.MemberProgressDashboard.to, routes.MemberProgressDashboard.as);
      } else {
          Router.replace(routes.MemberDashboard.to, routes.MemberDashboard.as);
      }
  } catch (error) {
      console.error(error);
  }
  </code></pre>
  
  <p>I honestly don't know what's happening or why refetch wouldn't work. Would refactoring into hooks help? Does anyone have any idea?</p>