中继订阅正确使用方法?

时间:2018-04-08 14:07:28

标签: reactjs graphql relay

目前,我必须遍历连接中的现有记录,以检查记录是否已经存在,并且只有在没有记录的情况下才会添加新边缘。我需要这样做的原因是,当页面加载时,CommentContainer会检索注释,但订阅也会获得所有注释,导致每个注释都被复制。

App.js:

const AppContainer = compose(
  lifecycle({
    componentDidMount() {
      commentSubscription();
    },
  }),
)(App);

我的订阅:

import { requestSubscription, graphql } from 'react-relay';
import { ConnectionHandler } from 'relay-runtime';

import environment from '../app/environment/environment';

const subscription = graphql`
  subscription commentSubscription {
    commentAdded {
      id
      ...commentContainer_comment
      audio {
        id
      }
    }
  }
`;

export default () => requestSubscription(
  environment,
  {
    subscription,
    onError: error => console.error(error), // eslint-disable-line no-console
    updater: (store) => {
      const commentAdded = store.getRootField('commentAdded');
      const audioRecord = commentAdded.getLinkedRecord('audio');
      const audioId = audioRecord.getValue('id');
      const audioProxy = store.get(audioId);
      const connection = ConnectionHandler.getConnection(
        audioProxy,
        'commentsContainer_comments',
      );

      if (connection) {
        const existingRecords = connection.getLinkedRecords('edges');
        const recordAlreadyExists = existingRecords.some((existingRecord) => {
          const node = existingRecord.getLinkedRecord('node');
          const existingId = node.getValue('id');
          const commentId = commentAdded.getValue('id');

          return existingId === commentId;
        });

        if (!recordAlreadyExists) {
          const edge = ConnectionHandler.createEdge(store, connection, commentAdded, 'CommentPayloadEdge');

          ConnectionHandler.insertEdgeBefore(connection, edge);
        }
      }
    },
  },
);

CommentsContainer:

import { compose } from 'recompose';
import { graphql } from 'react-relay';
import { fragmentContainer } from 'recompose-relay-modern';

import Comments from './comments';

const fragments = graphql`
  fragment commentsContainer_audio on Audio {
    id
    ...commentBoxContainer_audio
    comments(
      first: $count
      after: $cursor
    ) @connection(key: "commentsContainer_comments") {
      edges {
        node {
          commentId
          ...commentContainer_comment
        }
      }
    }
  }
`;

export default compose(
  fragmentContainer(fragments),
)(Comments);

CommentContainer:

import { compose } from 'recompose';
import { fragmentContainer } from 'recompose-relay-modern';
import { graphql } from 'react-relay';

import Comment from './comment';

const fragments = graphql`
  fragment commentContainer_comment on Comment {
    id
    body
    dateAdded
    user {
      userName
    }
  }
`;

export default compose(
  fragmentContainer(fragments),
)(Comment);

这是使用中继订阅的正确方法吗?在每个评论中循环检查它是否已经存在似乎效率低下。

1 个答案:

答案 0 :(得分:1)

我无法添加评论我不在50rep。我现在正在努力订阅。我可以告诉你,循环不是正确的方法 “DataID(type):记录的全局唯一或客户端生成的标识符,存储为字符串。” ,这是Relay Modern docs的形式。 如果找到重复的ID,Relay会自动检查控制台中是否也会抛出错误。在我的订阅中,我使用3种突变类型:CREATED,UPDATED,DELETED。因此,对于每种突变类型,我使用一个开关:

updater: (store) => {
      const getRootField = store.getRootField('UserSubscription');
      const mutation = getRootField.getValue('mutation');
      const node = getRootField.getLinkedRecord('node');
      switch (mutation) {
        case 'CREATED': {
          const clientProxy = store.get('client:root:viewer:allUsers');
          const newEdge = ConnectionHandler.createEdge(
            store,
            clientProxy,
            node,
            'UserEdge',
          );
          ConnectionHandler.insertEdgeBefore(clientProxy, newEdge);
        }
          break;
        case 'UPDATED':
          console.log('Updated');
          break;
        case 'DELETED': {
          const nodeId = node.getDataID();
          console.log(nodeId);
          store.delete(nodeId);
        }
          break;
        default:
          console.log('Something is wrong');
      }