0

I have 2 react components on the same page,

  • Component 1 query a list of users
  • Component 2 subscribe to the event of creating a new user

I can’t figure out a way to update the results of the component 1 based on the results of component 2's subscription.
Component1:

class Comp1 extends React.Component {

    render() {
        return (
            <div>
            {this.props.data.loading? <span>loading…</span>
        : <span> //show the list of users </span>       }
        </div>
                    );
    }
}

export default graphql(queryAllUsers)(Comp1) ;

Component2 :

class Comp2 extends React.Component {
   constructor(props) {
     super(props);
        this.state = {
        newUserCreated: false
            }
   }
 subscribeToNewUser() {
    this.subscription = this.props.data.subscribeToMore({
        document: subscribeToNewUsersQuery,
        variables: {//        },
    });
    }
    render() {
        return (
            <div>
            {this.state.newUserCreated}
        </div>
                    );
    }
}
tahayk
  • 492
  • 1
  • 5
  • 20

2 Answers2

3

The solution is to use a reducer function with query of the first component:

class Comp1 extends React.Component {
  render() { ... }
}

export default graphql(queryAllUsers, {
      options: (ownProps) => {
        return ({
            variables: { ...
            },
            reducer: (previousResult, action) => {
              if (action.type === "APOLLO_SUBSCRIPTION_RESULT" && action.operationName === "subscribeToNewUsersQuery") {
                //update the previousResult
                return previousResultWithNewData;
              } else return previousResult;
            })
        }
      })(Comp1);
tahayk
  • 492
  • 1
  • 5
  • 20
2

I guess the easiest way is to use the query in the first component too and add the subscription to it via the subscribeToMore function.

Could look like this:

...

subscribeToNewUser() {
    this.subscription = this.props.queryAllUsers.subscribeToMore({
      document: subscribeToNewUsersQuery,
      variables: { /* your variables */ },
      updateQuery: (previousResult, { subscriptionData }) => {
        const changedItem = subscriptionData.data.<subscriptionName>;
        if (changedItem !== undefined && changedItem !== null) {
          return // update previous result
        }
        return previousResult;
      },
    });
  }


  ...

  export default graphql(queryAllUsers, {
    name: "queryAllUsers"
  })
  ...
  (Comp1)

Therein you have the updateQuery functionality which will be called on the subscription event. When the resulting data is good you can update the store, e.g. push the new value to the users array

tahayk
  • 492
  • 1
  • 5
  • 20
Locco0_0
  • 3,420
  • 5
  • 30
  • 42
  • yes this could work, but for some performance reasons I want to have only 1 subscription done by the Comp1 only, and edit other component's queries according to that subscription. – tahayk Mar 31 '17 at 09:35
  • 1
    Than you could check the reducer functionality of the query [short reducer docu](http://dev.apollodata.com/react/cache-updates.html#resultReducers). Here you could catch the subscription action type and the related subscription and update the store – Locco0_0 Mar 31 '17 at 10:17
  • thank you very much, this is what I was looking for. – tahayk Mar 31 '17 at 10:31