TL;DR: React と Relay に関するさまざまなリソースを読み、react-relay を使用してプロトタイプ アプリを構築した後、助けなしでは解決できない問題に遭遇しました。どのデータを保存するかをミューテーションに伝える方法についてです。
User
エンティティの詳細を表示するコンポーネントがあります。リレー クエリを介して読み込まれます。このコンポーネントには<input />
、ユーザーの名前を含むフィールドと、呼び出しをトリガーする保存ボタンがありrelay.commitUpdate(...)
ます。入力フィールドでユーザーの名前を変更して保存をクリックすると、変更された名前ではなく、元の名前がバックエンドに送信されることがわかります。
私はアプリを構築しており、これらのデータを変更して保存できるエンティティreact-relay
に関する詳細を表示するコンポーネントに取り組んでいます。Master-Detail-Patternuser
の詳細部分です。
データのロードと変更は正常に機能します。ただし、変更はバックエンドにコミットされません。データの更新には、リレー ミューテーションを使用しようとしています。
保存をクリックすると、Chrome ブラウザーの開発者コンソールで、変更されていないデータがバックエンドに送信されていることがわかります。何が恋しいですか?これが私がこれまでに持っているものです(Typescriptコード)。
onSaveClick()
(更新:コンポーネントのgetVariables()
メソッドとミューテーションのメソッドにブレークポイントを配置するとonSaveClick
、プロパティthis.props.user
に変更が含まれているのに対しthis.props.user
、getVariables()
初期データが返されていることがわかります。)
export interface IUserDetailsProps { user: User }
export interface IUserDetailsStates { user: User }
class UserDetails extends React.Component<IUserDetailsProps, IUserDetailsStates> {
constructor(props: IUserDetailsProps) {
super(props);
this.state = { user: this.props.user };
}
public onFirstNameChange(event: any) {
let user = this.state.user;
this.state.user.firstName = event.target.value;
this.props.user.firstName = event.target.value; // is this needed?
this.setState({ user: user });
}
public onSaveClick() {
this.props.relay.commitUpdate(new UserMutation({ user: this.props.user }));
}
public render(): JSX.Element {
let user: User = this.props.user;
return <div>
<input type="text" value={user.firstName} onChange={this.onFirstNameChange.bind(this)} />
<button onClick={this.onSaveClick}>Save</button>
</div>;
}
}
class UserMutation extends Relay.Mutation {
public getMutation() {
return Relay.QL`mutation {saveUser}`;
}
public getVariables() {
return this.props.user;
}
public getFatQuery() {
return Relay.QL`
fragment on UserPayload {
user {
id,
firstName
}
}
`;
}
public getConfigs() {
return [{
type: "FIELDS_CHANGE",
fieldIDs: {
user: this.props.user.id
}
}];
}
static fragments = {
user: () => Relay.QL`
fragment on User {
id,
firstName
}
`
}
}
export default Relay.createContainer(UserDetails, {
fragments: {
user: () => Relay.QL`
fragment on User {
id,
firstName,
${UserMutation.getFragment("user")}
}
`
}
});
解決策の試み:
ユーザーの名の入力フィールドの行を次のように変更しました。
<input type="text"
ref={(ref) => {
this.myTextBox = ref;
ref.value = this.props.user.firstName;
}} />
変更イベント ハンドラを削除し、すべてのstate
コードを削除しました。
私のクリックハンドラーは次のようになります。
public onSaveClick() {
let user = Object.assign({}, this.props.user);
user.firstName = this.myTextBox.value;
this.props.relay.commitUpdate(new UserMutation({user: user}));
}
ミューテーションに渡されたユーザー オブジェクトにfirstName
は、テキスト入力で変更した新しい値が含まれていることがわかります。しかし、リレーは変更user
されていないものをバックエンドに送信します。私の問題を示すスクリーンショットは次のとおりです。