Isaac
Isaac

Reputation: 12894

GQL doesnt automatically invoke query

I have two components as below

SongList.js

import React, { Component } from 'react';
import gql from 'graphql-tag';
import { graphql } from 'react-apollo';
import { Link } from 'react-router';

class SongList extends Component {
  renderSongs() {
    return this.props.data.songs.map(song => {
      return (
        <li key={song.id} className="collection-item">
          {song.title}
        </li>
      );
    });
  }
  render() {
    if (this.props.data.loading) {
      return <div>Loading...</div>;
    }
    return (
      <div>
        <ul className="collection">
          {this.renderSongs()}
        </ul>
        <Link 
          to="/songs/new"
          className="btn-floating btn-large red right"
        >
          <i className="material-icons">add</i>
        </Link>
      </div>
    );
  }
}

const query = gql`
  {
    songs {
      id,
      title
    }
  }
`;

export default graphql(query)(SongList);

SongCreate.js

import React, { Component } from 'react';
import gql from 'graphql-tag';
import { graphql } from 'react-apollo';
import { Link, hashHistory } from 'react-router';

class SongCreate extends Component {
  constructor(props) {
    super(props);

    this.state = { title: '' }
  }

  onSubmit(event) {
    event.preventDefault();

    this.props.mutate({
      variables: {
        title: this.state.title
      }
    }).then(() => hashHistory.push('/'));
    // .catch((err) => console.log('DEBUG::err', err));

  }
  render() {
    return (
      <div>
        <Link to="/">
          Back
        </Link>
        <h3>Create a New Song</h3>
        <form onSubmit={this.onSubmit.bind(this)}>
          <label>Song Title: </label>
          <input 
            onChange={event => this.setState({ title: event.target.value })}
            value={this.state.title}
          />
        </form>
      </div>
    );
  }
}

const mutation = gql`
  mutation AddSong($title: String){
    addSong(title: $title) {
      title
    }
  }
`;

export default graphql(mutation)(SongCreate);

Basically the situation I'm facing is, in SongCreate component, once successfully mutate the addSong method, it will navigate back to SongList, however, I don't see the new song on SongList, and in order for me to see that, I have to refresh the page. It seems to me that the query at SongList doesnt get invoked?

Upvotes: 0

Views: 143

Answers (2)

Isaac
Isaac

Reputation: 12894

It appears that due to the reason the query been executed once, and when you add a new item and route back to the listing page, query will not rerun due to caching. So in order to fix that, we can refetch the query. In SongCreate component, we can define refetchQueries within mutate as below:

this.props.mutate({
      variables: {
        title: this.state.title
      },
      refetchQueries: [{ query: gql`.........` }] //<======
    }).then(() => hashHistory.push('/'));

Upvotes: 0

You need to query the same fields on the mutation results and the query results. That way, the internal cache of apollo will be updated accordingly (see doc section)

const mutation = gql`
  mutation AddSong($title: String){
    addSong(title: $title) {
      id         <==== Added this to match the query 
      title
    }
  }
`;

I also suggest that you play around with the chrome extension to view the apollo cache

Upvotes: 1

Related Questions