2016-08-24 5 views
0

私はUserオブジェクトの更新トリガする必要がありRelay.Mutation作成:実行、リレーはへuserを通過すると中継変異で未解決の小道具を扱うにはどうすればいいですか?

// I initially passed this.props.user to the mutation 
this.props.relay.commitUpdate(new UserMutation({ user: this.state.user }) 

:私はこのように私のコンポーネントUserDetailsにこの変異を使用してい

class UserMutation extends Relay.Mutation { 
    public getMutation() { 
     return Relay.QL`mutation {saveUser}`; 
    } 

    public getVariables() { 
     return { 
      id: this.props.user.id, 
      loginName: this.props.user.loginName, 
      firstName: this.props.user.firstName, 
      lastName: this.props.user.lastName, 
      mail: this.props.user.mail 
     } 
    } 

    public getFatQuery() { 
     return Relay.QL` 
      fragment on UserPayload { 
       user { 
        id, 
        loginName, 
        firstName, 
        lastName, 
        mail 
       } 
      } 
     `; 
    } 

    public getConfigs() { 
     return [{ 
      type: "FIELDS_CHANGE", 
      fieldIDs: { 
       user: this.props.user.id 
      } 
     }]; 
    } 

    static fragments = { 
     user:() => Relay.QL` 
      fragment on User { 
       id, 
       // I initially had only id here 
       loginName, 
       firstName, 
       lastName, 
       mail 
      } 
     ` 
    } 
} 

をバックエンドでidのみが設定され、他のプロパティはありません。入力変数に他のフィールドがないため、突然変異は実行されません。

突然変異をデバッグした後、this.props.userがid以外のすべてのフィールドにundefinedを設定していることがわかりました。ただし、this._unresolvedProps.useruserで、すべてのフィールドが正しく設定されています。

this.propsthis._unresolvedPropsに置き換えると、必要なデータがすべてバックエンドに送信され、エラーは発生せずに突然変異が実行されます。フロントエンドキャッシュも正しく更新されているようです(他のコンポーネントではfirstNameなどのフィールドが更新されます)。しかし、私はこれが正しい道であるとは思っていません。

私は何が間違っていますか? loginName

UPDATE

UserDetails成分負荷のユーザーデータと、これらのプロパティを変更するテキストボックスを提供します。対応するリレーコンテナは、次のようになります

私は、テキスト入力ハンドラ内のテキストボックスの変更を処理
export default Relay.createContainer(UserDetails, { 
    fragments: { 
     user:() => Relay.QL` 
      fragment on User { 
       id, 
       loginName, 
       firstName, 
       lastName, 
       mail, 
       roles { 
        id, 
        name 
       }, 
       ${UserMutation.getFragment("user")} 
      } 
     ` 
    } 
}); 

...

public handleTextInput(fieldName: string, event: any) { 
    let user = this.state.user; 

    switch (fieldName) { 
     case "loginName": { 
      user.loginName = event.target.value; 
      break; 
     } 
     case "firstName": { 
      user.firstName = event.target.value; 
      break; 
     } 
     case "lastName": { 
      user.lastName = event.target.value; 
      break; 
     } 
     case "mail": { 
      user.mail = event.target.value; 
      break; 
     } 
    } 

    this.setState({ user: user }); 
} 
...と私は今、合格提出するハンドラに提出形成変異 this.state.user

public handleSubmit(e: any) { 
    e.preventDefault(); 
    this.props.relay.commitUpdate(new UserMutation({ user: this.state.user }), { 
     onSuccess: (response: any) => { 
      this.setState({ user: response.saveUser.user }); 
     } 
    }); 
} 

私はC#のバックエンドを使用します。graphql-dotnet

public class ApplicationSchema : Schema 
{ 
    public ApplicationSchema() 
    { 
     this.Query = new ApplicationQuery(); 
     this.Mutation = new ApplicationMutation(); 
    } 
} 

public class ApplicationMutation : ObjectGraphType 
{ 
    public ApplicationMutation() 
    { 
     this.Name = "Mutation"; 

     // save a user 
     this.Field<UserPayloadType>(
      "saveUser", 
      arguments: new QueryArguments(
      new QueryArgument<NonNullGraphType<UserInputType>> 
      { 
       Name = "input", 
       Description = "the user that should be saved" 
      }), 
      resolve: context => 
       { 
        var userInput = context.Argument<UserInput>("input"); 
        var clientMutationId = userInput.ClientMutationId; 

        var user = MemoryRepository.UpdateUser(new User() 
        { 
         Id = userInput.Id, 
         LoginName = userInput.LoginName, 
         FirstName = userInput.FirstName, 
         LastName = userInput.LastName, 
         Mail = userInput.Mail 
        }); 

        return new UserPayload() 
        { 
         ClientMutationId = clientMutationId, 
         User = user 
        }; 
       }); 
    } 
} 

public class UserInputType : InputObjectGraphType 
{ 
    public UserInputType() 
    { 
     this.Name = "UserInput"; 

     this.Field<NonNullGraphType<StringGraphType>>("id", "The id of the user."); 
     this.Field<NonNullGraphType<StringGraphType>>("loginName", "The login name of the user."); 
     this.Field<NonNullGraphType<StringGraphType>>("firstName", "The first name of the user."); 
     this.Field<NonNullGraphType<StringGraphType>>("lastName", "The last name of the user."); 
     this.Field<NonNullGraphType<StringGraphType>>("mail", "The mail adress of the user."); 

     this.Field<NonNullGraphType<StringGraphType>>("clientMutationId", "react-relay property."); 
    } 
} 

public class UserPayloadType : ObjectGraphType 
{ 
    public UserPayloadType() 
    { 
     this.Name = "UserPayload"; 

     this.Field<NonNullGraphType<UserType>>("user", "The user."); 

     this.Field<NonNullGraphType<StringGraphType>>("clientMutationId", "react-relay property."); 
    } 
} 

public class UserType : ObjectGraphType 
{ 
    public UserType() 
    { 
     this.Name = "User"; 
     this.Field<NonNullGraphType<StringGraphType>>("id", "The id of the user."); 
     this.Field<NonNullGraphType<StringGraphType>>("loginName", "The login name of the user."); 
     this.Field<NonNullGraphType<StringGraphType>>("firstName", "The first name of the user."); 
     this.Field<NonNullGraphType<StringGraphType>>("lastName", "The last name of the user."); 
     this.Field<NonNullGraphType<StringGraphType>>("mail", "The mail adress of the user."); 

     Field<ListGraphType<RoleType>>("roles", resolve: context => MemoryRepository.GetRolesOfUser(context.Source as DomainModel.Models.User)); 
    } 
} 
+0

サーバー側のGraphQL変異「saveUser」を表示できますか?問題は 'saveUser'である可能性があります。 –

+0

また、Relayコンテナの 'fragments'フィールドを追加してください。 –

+0

必要なコードフラグメントを追加しました。ありがとう。 –

答えて

2

リレーコンテナはUserフラグメントを正しくフェッチしていますか?ユーザーのidフィールドにはstatic fragmentsの定義フラグメントがあるので、親リレーコンポーネントがそれらをすべてフェッチしているのだろうかと思います。

あなたの突然変異は実際にこれらのフィールドに依存しているので、それらをfragmentsプロパティに追加してください。

class UserMutation extends Relay.Mutation { 
    public getMutation() { ... } 

    // getVariables, FatQuery and Configs ... 

    static fragments = { 
     user:() => Relay.QL` 
      fragment on User { 
       id, 
       loginName, 
       firstName, 
       lastName, 
       mail 
      } 
     ` 
    } 
} 

このフラグメントを、あなたの突然変異を使用するリレーコンポーネントに含めるようにしてください。 例リアクションリレーコンポーネント:

import UserMutation from 'mutations/user'; 

class User extends Component { 
    commit(e) { 
    Relay.Store.commitUpdate(
     new UserMutation({ 
     user: this.props.user 
     }) 
    ); 
    } 

    render() { 
    return (
     <div>Hello</div> 
    ); 
    } 
}; 

export default Relay.createContainer(User, { 
    fragments: { 
    user:() => Relay.QL` 
     fragment on User { 
     ${UserMutation.getFragment('user')} 
     } 
    `, 
    } 
}); 
+0

Re:突然変異の 'フラグメント'のid以外のプロパティー、idのようなプロパティー(例えば 'FIELDS_CHANGE' config)の依存関係、楽観的な応答で更新されたプロパティーを'フラグメント 'に含める必要があります。リレーは、ファットクエリーを調べることによってフェッチするフィールドを決定します。したがって、楽観的応答が突然変異で定義されていない場合、id以外のフィールドはフラグメントに含める必要はありません。 –

+0

ありがとう、私は親リレーコンテナのコー​​ドを追加しました。また、 'loginName'などのすべてのプロパティを突然変異フラグメントに追加しました。現在、ユーザーはバックエンドに送信されますが、変更されていないプロパティはすべてのテキスト入力を無視します。私は質問に関連するコードの断片を追加しました。私は正しい方法でユーザーを変更しますか? –

+0

最後に、リレーと互換性があるようにスキーマを調整する必要がありました。バックグラウンドでgraphql-dotnetを使用しています。グラフの種類を変更する必要があります(ユーザーのコレクションに必要なプロパティをすべて追加するなど)。フラグメントのすべてのプロパティを一覧表示することが重要だったので、御支援をありがとうございます。 –

0

使用REQUIRED_CHILDRENとコンポーネントの状態を更新します。これは私が、突然変異のために定義されたものです。

FIELDS_CHANGEを使用するのではなく、REQUIRED_CHILDRENを使用すると、返された保存済みオブジェクトを店舗に追加することができます。あなたがどうなるのかは、このようなあなたのgetConfigsを設定されています

getConfigs() { 
    return [{ 
    type: 'REQUIRED_CHILDREN', 
     children: [ 
     Relay.QL` 
      fragment on UserPayload { 
      user { 
       id 
       loginName 
       firstName 
       lastName 
       mail 
      } 
      } 
     ` 
     ] 
    }] 
} 

そして変化

このようなあなたのcommitUpdate:あなたが見ることができるように

this.props.relay.commitUpdate(
    new UserMutation({user: this.props.user}), 
    { 
    onSuccess: response => this.setState({ 
     user: response.user, 
    }), 
    onError: err => console.log(err) 
    } 
); 

、するonSuccessコールバックは、あなたがactionCreatorを呼び出して置くようにしますあなたのアプリケーションの状態に新しいユーザー。これは、アプリケーションで使用している状態管理を使用して行います。この場合は、単にsetStateです。

REQUIRED_CHILDREN configは、追加の子を突然変異クエリに追加するために使用されます。たとえば、これを使用して、突然変異によって作成された新しいオブジェクトのフィールドを取得する必要があるかもしれません(リレーは通常、そのオブジェクトに対して何も取得していないためフェッチを試みません)。 REQUIRED_CHILDRENコンフィグレーションの結果としてフェッチ

データは、クライアントストアに書き込まれていませんが、あなたは、あなたがcommitUpdate()に渡すことするonSuccessコールバックでそれを処理するコードを追加することができます

There is more information in the documentation about REQUIRED_CHILDREN here.

+0

このヒントをありがとう。しかし私の実際の問題は、 'user'を取り戻すのではなく、' user'を突然変異に渡すことです。 'getVariables()'にデバッグすると、 'this.props.user'が' id'を設定したことがわかります。したがって、バックエンドに突然変異を起こそうとすると、入力に 'id'だけが設定されていて、' firstName'、 'lastName'ではなく、' UserInput '型の 'Variable' $ input_0 '期待値を受け取ります。 –

+0

多分あなたの突然変異をAPI上に置くことができますか?そこに問題があるかもしれません。 – alexi2

+0

ありがとう、私は突然変異の関連バックエンドコードを追加しました。 –

関連する問題