react-router-relay 和 Relay 模式不一致?

Is react-router-relay inconsistent with the Relay pattern?

我正在项目中使用 react-router-relay。考虑到每个组件基本上都以一个与根查询同名的片段结束,这个设计对我来说似乎不太对劲。每个组件不应该能够在根查询下具有任意类型的唯一命名片段吗?这可能使用这个包还是我的想法在这里有缺陷?

编辑: 可能我的问题有点含糊。我的问题是,对于 react-router-relay 定义的查询属性,本质上有两个规则强制执行在我看来是一个奇怪的设计模式。这两条规则是:

  1. 每个查询只能深入 "one level"。
  2. 每个查询都必须映射到使用它的组件上具有相同名称的片段。

这给您留下了一个场景,您可以:

  1. 对每个组件使用相同的 "viewer" 查询并在每个组件上定义免费的 "viewer" 片段。尽管名称相同,但这些片段都将定义不同的数据要求,这看起来很混乱。
  2. 您为不同的组件创建唯一的片段名称,然后根据您要获取的数据类型使用不同的名称重复完全相同的根查询,这看起来非常愚蠢。

好问题。当您处理 Relay 时,您的想法是正确的,因为每个组件都应该有自己的片段,以便查询本身准确地映射到该特定组件所需的数据。片段的命名可以任意命名,但类型不能随意。它必须是 Root Query 对象(或您要将片段附加到的任何字段)下的声明类型。否则该片段将抛出一个错误,提示您无法在 Query 或字段上查询该类型。

例如:

var componentOneFragment = Relay.QL`
    fragment on User {
        name
    }
`;

这里要注意的一件事是,您不需要为像 fragment userFragment on User { ... } 这样的片段命名。当通过声明 ${Component.getFragment(componentOneFragment)} 从路由器中的中继查询动态引用组件片段时,这将为您提供更大的灵活性。希望这对您有所帮助!

编辑:

Use the same "viewer" query for every component and define a complimentary "viewer" fragment on each component. These fragments would all define different data requirements, despite having the same name, which seems very confusing.

尽管碎片的相同名称可能看起来令人困惑,但这是思考事物的最佳方式。每个组件确实有不同的数据需求,所以它们的 Relay 容器自然会有不同的片段,但仍然在相同的片段名称下。

此片段可能包含在需要 User 数据的中继容器之一中:

const WidgetList = Relay.createContainer(/* ... */, {
  initialVariables: {
    color: null,
    size: null,
    limit: null
  },

  fragments: {
    viewer: () => Relay.QL`
      fragment on User {
        widgets(color: $color, size: $size, first: $limit) {
          edges {
            node {
              name,
            },
          },
        },
      }
    `
  }
});

虽然此片段(仍具有相同的名称)可能包含在另一个需要 Widget 数据的中继容器中:

const ActionsList = Relay.createContainer(/* ... */, {
  initialVariables: {
    input: null
  },

  fragments: {
    viewer: () => Relay.QL`
      fragment on Widget {
        actions(input: $input) {
          edges {
            node {
              name,
            },
          },
        },
      }
    `
  }
});

只要 UserWidget 都可以在同一个 GraphQL 查询中动态使用(即 $Component.getFragment('viewer'))都是根查询对象下的类型。