【问题标题】:Using writeFragment to Update a Field Belonging to an Object?使用 writeFragment 更新属于对象的字段?
【发布时间】:2018-09-26 21:17:14
【问题描述】:

我正在尝试让我的第一个 writeFragment 工作。

这是物体的形状:

resolutions {
  _id
  name
  completed
  goals {
    _id
    name
    completed
  }
}

我刚刚在客户端上运行了一个突变,成功添加了一个新的goal,现在我正在尝试让客户端页面自动更新并显示刚刚添加的新目标。

我有 readFragment 工作。它成功读取了分辨率。我正在阅读决议,而不是目标,因为作为属于决议的字段,目标没有自己的 id。

这是我的update 函数,显示readFragmentwriteFragment

<Mutation
  mutation={CREATE_GOAL}
  update={(cache, { data: { createGoal } }) => {
    let resId = 'Resolution:' + resolutionId;

    const theRes = cache.readFragment({
      id: resId,
      fragment: GET_FRAGMENT_GOAL,
    });

    theRes.goals = theRes.goals.concat([createGoal]); //<== THIS WORKS

    cache.writeFragment({
      id: resId,
      fragment: SET_FRAGMENT_GOAL,
      data: { __typename: 'Resolution', goals: theRes.goals },
      });
    }}
>

...这是片段的 gql:

   const GET_FRAGMENT_GOAL = gql`
    fragment targetRes on resolutions {
      name
      completed
      goals {
        _id
        name
        completed
      }
    }
  `;


  const SET_FRAGMENT_GOAL = gql`
    fragment targetGoal on resolutions {
      __typename
      goals
    }
  `;

这是我得到的控制台错误:

您正在使用简单(启发式)片段匹配器,但您的查询包含联合或接口类型。

Apollo 客户端将无法准确映射片段。要消除此错误,请使用文档中所述的 IntrospectionFragmentMatcher:http://dev.apollodata.com/react/initialization.html#fragment-matcher

我阅读了 IntrospectionFragmentMatcher ,对于我的情况来说,它看起来有点矫枉过正。看来我做错了什么。这是我同时遇到的另一个错误:

Uncaught (in promise) TypeError: Cannot read property 'data' of undefined

我对 writeFragment 的调用有什么问题?

【问题讨论】:

  • 也许goals 的子字段应该像GET_FRAGMENT_GOAL 一样添加到SET_FRAGMENT_GOAL 中?

标签: graphql apollo react-apollo apollo-client


【解决方案1】:

经过几个小时的学习,我了解了很多关于片段的知识!

我让它工作了。以下是更新的片段和查询定义:

import gql from "graphql-tag";

let resolutionQueryFragments = {
    goalParts: gql`
    fragment goalParts on Goal {
        _id
        name
        completed
    }
  `,
};


resolutionQueryFragments.resolutionGoals = gql`
    fragment resolutionGoals on Resolution {
        goals{
            _id
            name
            completed   
        }
    }
`;

const GET_RESOLUTIONS = gql`
  query Resolutions {
    resolutions {
      _id
      name
      completed
      ...resolutionGoals
    }
     user {
      _id
    }
  }
  ${resolutionQueryFragments.resolutionGoals}
`;

const CREATE_RESOLUTION = gql`
    mutation createResolution($name: String!) {
      createResolution(name: $name) {
        __typename
        _id
        name
        ...resolutionGoals
        completed
      }
    }
    ${resolutionQueryFragments.resolutionGoals}
`;

const GET_RESOLUTIONS_FOR_MUTATION_COMPONENT = gql`
  query Resolutions {
    resolutions {
      _id
      name
      completed
      ...resolutionGoals
    }
  }
     ${resolutionQueryFragments.resolutionGoals}
`;

const CREATE_GOAL = gql`
  mutation createGoal($name: String!, $resolutionId: String!) {
    createGoal(name: $name, resolutionId: $resolutionId) {
        ...goalParts
      }
  }
     ${resolutionQueryFragments.goalParts}
`;

export {resolutionQueryFragments, GET_RESOLUTIONS, GET_RESOLUTIONS_FOR_MUTATION_COMPONENT, CREATE_RESOLUTION, CREATE_GOAL}

...这是更新后的 Mutation 组件:

import React, {Component} from "react";
import gql from "graphql-tag";
import {graphql} from "react-apollo";
import {Mutation} from "react-apollo";
import {withApollo} from "react-apollo";
import {resolutionQueryFragments, CREATE_GOAL} from '../../imports/api/resolutions/queries';

const GoalForm = ({resolutionId, client}) => {
    let input;

    return (
        <Mutation
            mutation={CREATE_GOAL}
            update={(cache, {data: {createGoal}}) => {
                let resId = 'Resolution:' + resolutionId;
                let currentRes = cache.data.data[resId];
                let theGoals = cache.readFragment({
                    id: resId,
                    fragment: resolutionQueryFragments.resolutionGoals
                });
                theGoals = theGoals.goals.concat([createGoal]);
                cache.writeFragment({
                    id: resId,
                    fragment: resolutionQueryFragments.resolutionGoals,
                    data: {goals: theGoals}
                });
            }}
        >
            {(createGoal, {data}) => (
                <div>
                    <form
                        onSubmit={e => {
                            e.preventDefault();
                            createGoal({
                                variables: {
                                    name: input.value,
                                    resolutionId: resolutionId
                                }
                            });
                            input.value = "";
                        }}
                    >
                        <input
                            ref={node => {
                                input = node;
                            }}
                        />
                        <button type="submit">Submit</button>
                    </form>
                </div>
            )}
        </Mutation>
    )
        ;
};

export default withApollo(GoalForm);

【讨论】:

    猜你喜欢
    • 2016-06-09
    • 2018-07-15
    • 2020-05-20
    • 2014-07-24
    • 2016-05-10
    • 2018-06-09
    • 2016-09-13
    • 2015-02-16
    • 1970-01-01
    相关资源
    最近更新 更多