简体   繁体   中英

after mutation relay modern connection handler is undefined

I'm doing a mutation of multiple items. But the connection handler in updater returns undefined. I'm dealing with the shopItems type, Here's the relevant schema

type Mutation {
  shopItem(input: itemsInput): addedItems
}

type addedItems {
  addedItems: [itemEdge]
}

type itemEdge {
  cursor: Int
  node: itemNode
}

type itemNode implements Node {
  id: ID!,
  name: String,
  price: Int
}

type Root {
  viewer: viewer
}

type viewer {
  id: ID!
  shopItems(ShopId: ID, SubCategoryId:ID, first:Int, last: Int): Item
}

type Item {
  pageInfo: PageInfo
  edges: [itemEdge]
}

this is the fragment for shopItems query,

module.exports = createFragmentContainer(
  Item,
  graphql`
    fragment item_viewer on viewer {
      // the global parent viewer id
      id,
      shopItems(first:$first,last:$last,ShopId:$ShopId,SubCategoryId:$SubCategoryId) @connection(key: "item_shopItems",filters:["first","last"]){

     // didn't want the pageInfo here yet but relay compiler enforces this because of @connection. It's basically returning null.
        pageInfo {
          hasNextPage
          endCursor
        }
        edges {
          cursor // returns null as well
          node {
            id
            name
            price
          }
        }
      }
    }
  `
)

the mutation for adding shopItems returns array of addedItems,

mutation addShopItemMutation($input: itemsInput) {
    shopItem(input: $input) {
      addedItems {
        node {
          id
          name
          price
        }
      }
    }
  }


commitMutation(
        environment,
        {
        ...
        updater: (store) => {
          const payload = store.getRootField('shopItem');

          //I've seen everyone using getLinkedRecord, but in my case the mutation return type is an array and it gives an error so I'm using getLinkedRecords. I think this is where the problem lies.

          const newItem = payload.getLinkedRecords('addedItems');
          this.sharedUpdate(store, this.props.viewerId, newItem)
        }
      })

sharedUpdate(store, viewerId, newItem) {

    //viewerProxy here is not undefined
    const viewerProxy = store.get(viewerId);

    //conn is undefined
    const conn = ConnectionHandler.getConnection(
    viewerProxy,
    'item_shopItems',
    );
    if(conn)  {
      ConnectionHandler.insertEdgeAfter(conn, newItem);
    }
  }

For some reason the connection returns undefined. Also when I console.log viewerProxy, I do see the connection key "item_shopItems" but the new edge doesn't appear there. Just in case, I'm using Node Js - Express on server side.

Another problem is that the addedItem is not singular, but an array.

you need using pagination for shopItems query:

module.exports = createPaginationContainer(
  ShopItems,
  {
    viewer: graphql`
      fragment ShopItems_viewer on Viewer {
        id
        shopItems(
          first: $count
          after: $cursor
          ShopId: $ShopId
          SubCategoryId: $SubCategoryId
        )
          @connection(
            key: "ShopItems_shopItems"
            filters: ["ShopId", "SubCategoryId"]
          ) {
          edges {
            cursor
            node {
              id
              name
              price
            }
          }
        }
      }
    `
  },
  {
    direction: 'forward',
    getConnectionFromProps(props) {
      return props.viewer.shopItems;
    },
    getFragmentVariables(prevVars, totalCount) {
      return {
        ...prevVars,
        count: totalCount
      };
    },
    getVariables(props, { count, cursor }, fragmentVariables) {
      return {
        count,
        cursor,
        ShopId: fragmentVariables.ShopId,
        SubCategoryId: fragmentVariables.SubCategoryId
      };
    },
    query: graphql`
      query ShopItemsQuery(
        $count: Int!
        $cursor: String
        $ShopId: ID
        $orderBy: ID
      ) {
        viewer {
          ...ShopItems_viewer
        }
      }
    `
  }
);

note: filters: [] in @connection without after , first , before and last

the mutation:

/**
 * @flow
 */
import { commitMutation, graphql } from 'react-relay';
import { ConnectionHandler } from 'relay-runtime';
import environment from '../utils/createRelayEnvironment';

type Options = {
  onSuccess: Function,
  onFailure: Function
};

const defaultCallbacks: Options = { onSuccess: () => {}, onFailure: () => {} };

const mutation = graphql`
  mutation AddShopItemMutation($input: itemsInput) {
    shopItem(input: $input) {
      addedItems {
        cursor
        node {
          id
          name
          price
        }
      }
    }
  }
`;

function sharedUpdater(store, viewer, addedItemsEdge, nameConnection, filters) {
  const viewerProxy = store.get(viewer.id);

  const connection = ConnectionHandler.getConnection(
    viewerProxy,
    nameConnection,
    filters // your connection undefined is do missing filters
  );

  if (connection) {
    ConnectionHandler.insertEdgeBefore(connection, addedItemsEdge);
  }
}

let nextClientMutationId = 0;

function commit(
  viewer: Object,
  input: Object,
  nameConnection: string,
  filters: Object, // { ShopId: ID, SubCategoryId: ID };
  // const { ShopId, SubCategoryId } = this.context.relay.variables
  cb: Options = defaultCallbacks
): any {
  nextClientMutationId += 1;

  return commitMutation(environment, {
    mutation,
    variables: {
      input: {
        ...input,
        clientMutationId: nextClientMutationId
      }
    },
    onCompleted: cb.onSuccess,
    onError: cb.onFailure,
    updater(store) {
      const payload = store.getRootField('addShopItem');

      sharedUpdater(
        store,
        viewer,
        payload.getLinkedRecords('addedItems'),
        nameConnection,
        filters
      );
    }
  });
}

export default { commit };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM