首页 文章

与Apollo客户端的片段组成:约定和样板

提问于
浏览
4

在Apollo应用程序(还有GraphQL / Relay)中,可以选择将数据需求集中到组件,或者最终自己组装大型GraphQL查询 . 我们选择将数据需求与组件共存,因为我们希望在长时间内具有更好的可维护性,因为您不需要查看整个组件树或页面来查看所有数据要求,并且可以在本地添加新要求 .

我想更好地了解如何使用Apollo客户端编写GraphQL片段 . 我知道该怎么做,但我想知道如何才能做得更好 .

目前,编写我的片段涉及相当多的样板,特别是当我有组件只是传递属性未触及时 .

片段声明约定?

首先,我们来看一个简单的组件:

export const User = ({
  user: {
    firstName,
    lastName,
    job,
    email,
    pictureUrl,
    color
  },
  ...props
}) => (
  <UserWrapper {...props}>
    <UserAvatarWrapper>
      <Avatar
        firstName={firstName}
        lastName={lastName}
        color={color}
        src={pictureUrl}
      />
    </UserAvatarWrapper>
    <UserContentWrapper>
      {(firstName || lastName) &&
        <UserName>
          {firstName}
          {" "}
          {lastName}
          {" "}
          {email && <UserEmailInline>{email}</UserEmailInline>}
        </UserName>}
      {job && <UserJob>{job}</UserJob>}
    </UserContentWrapper>
  </UserWrapper>
);
User.fragments = {
  user: gql`
      fragment User on User {
          id
          firstName
          lastName
          pictureUrl: avatar
          job
          color
          email
      }
  `,
};

以下是一些选择 . 似乎在大多数示例中都使用了某种约定,但此约定在doc中并不明确 .

  • User.fragments 上使用的密钥 . 将它命名为与组件的propName user 完全相同是否有意义?

  • 片段的名称:按惯例似乎人们用组件的名称命名它,如果有用,则在片段的GraphQL类型后面加上它们 . (这里 UserUser 可能是矫枉过正的后缀) .

我认为在同一个应用程序中遵循相同的约定是很好的,这样所有的片段声明都是一致的 . 那么,更有经验的人可以帮我澄清这个似乎在许多Apollo例子中使用的约定吗?

减少碎片组成样板?

让我们按照我们设定的惯例考虑一个 Relationship 组件 .

const Relationship = ({ user1, user2 }) => (
  <RelationshipContainer>
      <RelationshipUserContainer>
        <User user={user1} />
      </RelationshipUserContainer/>
      <RelationshipUserContainer>
        <User user={user2} />
      </RelationshipUserContainer/>
  </RelationshipContainer>
);
Relationship.fragments = {
  user1: gql`
      fragment RelationshipUser1User on User {
          ...User
      }
      ${User.fragments.user}
  `,
  user2: gql`
      fragment RelationshipUser2User on User {
          ...User
      }
      ${User.fragments.user}
  `,
};

请注意,这里我必须使用2道具,你不一定要认为两个道具的数据要求是相同的 . 我们可以很容易地想象一个具有 me 道具和 friend 道具的组件,在这里您可以获得更多 me 道具的数据 .

这工作正常但很多样板和中间片段看起来很不必要 . 此外,它并不总是方便,因为从组件用户的角度来看,您必须知道能够使用它的2个片段名称 .

我尝试使用以下内容简化此操作

Relationship.fragments = {
  user1: User.fragments.user,
  user2: User.fragments.user,
};

这可以工作,但如果你这样做,那么片段名称不再是 RelationshipUserXUser ,而是 User ,这意味着它打破了封装,并且你需要在内部知道, Relationship 组件正在使用 User 组件 .

如果有一天, Relationship 组件切换到使用像 UserAlt 这样的替代表示,这将需要使用关系片段从所有组件进行重构,这是我想要避免的 . 我认为在这种情况下,修改应该只发生在 Relationship 组件中 .

结论

我想知道用Apollo组成片段的最佳实践,以便组件保持真正的封装,并且最好不涉及太多的样板 .

我已经做对了吗?

如果我真的想要撰写查询,那么所有这些样板都是不可避免的吗?

1 回答

  • 3

    这样做怎么样:

    const userFragment = gql`
      fragment Relationship_user on User {
        ...User_user
      }
      ${User.fragments.user}
    `;
    Relationship.fragments = {
      user1: userFragment,
      user2: userFragment,
    };
    

    除此之外,我建议您使用上面所示的片段名称作为范围,因为需要某种名称间距,因为否则您将更有可能两次使用相同的片段名称 .

    • User.fragments.user => User_user

    • Relationship.fragments.user => Relationship_user

相关问题