具有后续突变和缺失片段的中继 commitUpdate 回调

Relay commitUpdate callback with follow-up mutation and missing fragment

我有两个 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')},
      }
    `,

我在不更改任何 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 可以用作邀请 link 加入此应用程序中的组织。如果用户登录并转到 link: <host>/profile/join-organization/<organizationRowId>,突变将 运行 加入该人作为成员。在此用例中,router.state.isAdminfalse,因此新成员身份将被禁用为管理员。