使用后续突变和缺失片段中继 commitUpdate 回调

Posted

技术标签:

【中文标题】使用后续突变和缺失片段中继 commitUpdate 回调【英文标题】:Relay commitUpdate callback with follow-up mutation and missing fragment 【发布时间】:2017-03-17 10:04:00 【问题描述】:

我有两个单独工作的 GraphQL/Relay 突变。第一个创建一个项目。第二个运行一个连接两个项目的过程。

GraphQL

createOrganization(
  input: CreateOrganizationInput!
): CreateOrganizationPayload

createOrganizationMember(
  input: CreateOrganizationMemberInput!
): CreateOrganizationMemberPayload

input CreateOrganizationInput 
  clientMutationId: String
  organization: OrganizationInput!


input CreateOrganizationMemberInput 
  clientMutationId: String
  organizationMember: OrganizationMemberInput!


# Represents a user’s membership in an organization.
input OrganizationMemberInput 
  # The organization which the user is a part of.
  organizationId: Uuid!

  # The user who is a member of the given organization.
  memberId: Uuid!


type CreateOrganizationPayload 
  clientMutationId: String

  # The `Organization` that was created by this mutation.
  organization: Organization

  # An edge for our `Organization`. May be used by Relay 1.
  organizationEdge(
    orderBy: OrganizationsOrderBy = PRIMARY_KEY_ASC
  ): OrganizationsEdge

  # Our root query field type. Allows us to run any query from our mutation payload.
  query: Query

我希望能够运行createOrganization 突变,然后使用createOrganizationMember 突变将用户连接到组织。第二个突变有两个参数,其中一个是新创建的边。

我尝试将边缘传递给突变,但它希望突变能够getFragment。如何获取有效负载边缘的片段,以便将其传递到突变中?

反应中继

Relay.Store.commitUpdate(
      new CreateOrganizationMutation(
        organizationData: data,
        user,
        query,
      ), 
        onSuccess: response => 
          Relay.Store.commitUpdate(
            new CreateOrganizationMemberMutation(
              organization: response.createOrganization.organizationEdge.node,
              user,
            )
          );
        ,
      
    );

  fragments: 
    user: () => Relay.QL`
      fragment on User 
        $CreateOrganizationMutation.getFragment('user'),
        $CreateOrganizationMemberMutation.getFragment('user'),
      
    `,

【问题讨论】:

【参考方案1】:

我在不更改任何 GraphQL 的情况下解决了这个问题:

我创建了一个新的中继容器、路由和查询对象。它被配置为 发生两个突变中的第一个的容器的子路由。 id 为 新边通过路由路径名作为参数传递。路由器状态 变量也被传递。

路线

import Route from 'react-router';

function prepareProfileParams (params, location) 
  return 
    ...params,
    userId: localStorage.getItem('user_uuid'),
  ;

    // ProfileContainer has the component CreateOrganizationForm, which calls
    // the createOrganization mutation
    <Route
      path='profile'
      component=ProfileContainer
      queries=ProfileQueries
      prepareParams=prepareProfileParams
      onEnter=loginBouncer
      renderLoading=renderLoading
    >
      <Route path='join-organization'>
        <Route
          path=':organizationId'
          component=JoinOrganizationContainer
          queries=JoinOrganizationQueries
          renderLoading=renderLoading
        />
      </Route>
    </Route>

CreateOrganizationForm.js

    Relay.Store.commitUpdate(
      new CreateOrganizationMutation(
        organizationData: data,
        user,
        query,
      ), 
        onSuccess: response => 
          const organizationId = response.createOrganization.organizationEdge.node.rowId;
          router.push(
            pathname: `/profile/join-organization/$organizationId`,
            state: 
              isAdmin: true,
            ,
          );
        ,
      
    );

新的 Relay 容器 JoinOrganizationContainer 将挂钩到生命周期 方法来调用我们需要的第二个突变。第二个突变有一个 onSuccess 回调,它为我们的新对象执行 router.push 到页面 使用第一个突变创建。

JoinOrganizationContainer.js

    import React from 'react';
    import Relay from 'react-relay';
    import CreateOrganizationMemberMutation from './mutations/CreateOrganizationMemberMutation';

    class JoinOrganizationContainer extends React.Component 
      static propTypes = 
        user: React.PropTypes.object,
        organization: React.PropTypes.object,
      ;
      static contextTypes = 
        router: React.PropTypes.object,
        location: React.PropTypes.object,
      ;
      componentWillMount () 
        const user, organization = this.props;
        const router, location = this.context;

        Relay.Store.commitUpdate(
          new CreateOrganizationMemberMutation(
            user,
            organization,
            isAdmin: location.state.isAdmin,
          ), 
            onSuccess: response => 
              router.replace(`/organization/$organization.id`);
            ,
          
        );
      
      render () 
        console.log('Joining organization...');
        return null;
      
    

    export default Relay.createContainer(JoinOrganizationContainer, 
      initialVariables: 
        userId: null,
        organizationId: null,
      ,
      fragments: 
        user: () => Relay.QL`
          fragment on User 
            $CreateOrganizationMemberMutation.getFragment('user'),
          
        `,
        organization: () => Relay.QL`
          fragment on Organization 
            id,
            $CreateOrganizationMemberMutation.getFragment('organization'),
          
        `,
      ,
    );

JoinOrganizationQueries.js

    import Relay from 'react-relay';

    export default 
      user: () => Relay.QL`
        query  userByRowId(rowId: $userId) 
      `,
      organization: () => Relay.QL`
        query  organizationByRowId(rowId: $organizationId) 
      `,
    ;

以这种方式做事的一个意想不到的好处是,现在有一个可共享的 url,可用作加入此应用中的组织的邀请链接。如果用户已登录并转到链接:&lt;host&gt;/profile/join-organization/&lt;organizationRowId&gt;,则将运行突变以将该人加入为成员。在此用例中,router.state.isAdminfalse,因此新成员身份将作为管理员禁用。

【讨论】:

以上是关于使用后续突变和缺失片段中继 commitUpdate 回调的主要内容,如果未能解决你的问题,请参考以下文章

中继:有条件地在突变的胖查询中包含字段

使用中继环境的突变

如何在中继服务器中使用删除突变?

relayjs:使用中继进行身份验证,使用哪个突变?

中继突变:突变分页关联

使用 InputObjectType 实例作为中继突变的输入