Search code examples
reactjsgraphqlsubscriptiongraphql-js

Passing data through a GRAPHQL Subscription gives null on only one of the arguments


I have the following GRAPHQL subscription:

Schema.graphql
    type Subscription {
      booking: SubscriptionData
    }

    type SubscriptionData {
      booking: Booking!
      action: String
    }

And this is the resolver subsrciption file

Resolver/Subscription.js
const Subscription = {
  booking: {
    subscribe(parent, args, { pubsub }, info) {
      return pubsub.asyncIterator("booking");
    }
  }
};

export default Subscription;

Then I have the following code on the Mutation in question

pubsub.publish("booking", { booking: { booking }, action: "test" });

I have the follow subscription file in front end (React)

const getAllBookings = gql`
  query {
    bookings {
      time
      durationMin
      payed
      selected
      activity {
        name
      }
    }
  }
`;

const getAllBookingsInitial = {
  query: gql`
    query {
      bookings {
        time
        durationMin
        payed
        selected
        activity {
          name
        }
      }
    }
  `
};

class AllBookings extends Component {
  state = { allBookings: [] }

  componentWillMount() {
    console.log('componentWillMount inside AllBookings.js')
    client.query(getAllBookingsInitial).then(res => this.setState({ allBookings: res.data.bookings })).catch(err => console.log("an error occurred: ", err));
  }

  componentDidMount() {
    console.log(this.props.getAllBookingsQuery)
    this.createBookingsSubscription = this.props.getAllBookingsQuery.subscribeToMore(
      {
        document: gql`
          subscription {
            booking {
              booking { 
                time
                durationMin
                payed
                selected
                activity {
                  name
                   }
              }
              action
            }
          }
        `,
        updateQuery: async (prevState, { subscriptionData }) => {
          console.log('subscriptionData', subscriptionData)
          const newBooking = subscriptionData.data.booking.booking;
          const newState = [...this.state.allBookings, newBooking]
          this.setState((prevState) => ({ allBookings: [...prevState.allBookings, newBooking] }))
          this.props.setAllBookings(newState);
        }
      },
      err => console.error(err)
    );
  }
  render() {
    return null;
  }
}

export default graphql(getAllBookings, { name: "getAllBookingsQuery" })(
  AllBookings
);

And I get the following response:

data: {
booking: {booking: {...} action: null}}

I get that I am probably setting up the subscription wrong somehow but I don't see the issue.


Solution

  • Based on your schema, the desired data returned should look like this:

    {
      "booking": {
        "booking": {
          ...
        },
        "action": "test"
      }
    }
    

    The first booking is the field on Subscription, while the second booking is the field on SubscriptionData. The object you pass to publish should have this same shape (i.e. it should always include the root-level subscription field).

    pubsub.publish('booking', {
      booking: {
        booking,
        action: 'test',
      },
    })