Apollo学习笔记(3)mutations

1、Mutation Component

Apollo-client修改数据使用的是Mutation component.Mutation component 和Query component设计非常的相似,都是render prop模型。

Mutation组件接受的参数:第一个是mutation接受的和Query相对是mutation document,用gql包含字符串转义得到。

第二个是children:包含一个function ,告诉组件提交修改后返回的组件:包含loading, error, called, and data等参数。

示例:

import gql from "graphql-tag";
import { Mutation } from "react-apollo";

const ADD_TODO = gql`
  mutation AddTodo($type: String!) {
    addTodo(type: $type) {
      id
      type
    }
  }
`;

const AddTodo = () => {
  let input;

  return (
    <Mutation mutation={ADD_TODO}>
      {(addTodo, { data }) => (
        <div>
          <form
            onSubmit={e => {
              e.preventDefault();
              addTodo({ variables: { type: input.value } });
              input.value = "";
            }}
          >
            <input
              ref={node => {
                input = node;
              }}
            />
            <button type="submit">Add Todo</button>
          </form>
        </div>
      )}
    </Mutation>
  );
};

  mutation function的第一个参数是addTodo,代表这个mutation function 本身。Mutation的props中除了可以传入mutation之外,还可以传入的是variablesoptimisticResponserefetchQueries, 和update。注意这里,我们传入variables是通过addTodo传入而不是直接在props中传入,其效果是一样的。

<input ref={node=>{input=node;}}/>ref指向的是input标签本身,node代指本节点,input=node,代表input指向了《input》标签节点,这样input.value就代表输入框的值。

mutation function的第二个参数是{data,loading,error,called}等,如果不希望使用第二个参数,可以在Mutation component 的props上传入ignoreResults;

通过上述的修改操作,你会发现TODO列表并没有把我们刚刚增加的todo显示出来,这是由于Query组件监听的是cache,由于cache没有更新,仅仅是服务端更新了,所以页面没有更新。

2、更新缓存

更新缓存,我们需要用到update props

update 接受一个function,第一个参数代表cache,cache有cache.readQuery和cache.writeQuery可以让我们更新缓存,还有cache.readFragmentcache.writeFragment, 和 cache.writeData等。

第二个数据代表mutation函数的结果。如果执行乐观更新的话将会更新两次,一次是mutation 函数的结果,另一次是真实的数据。

示例:

const AddTodo = () => {
  let input;

  return (
    <Mutation
      mutation={ADD_TODO}
      update={(cache, { data: { addTodo } }) => {
        const { todos } = cache.readQuery({ query: GET_TODOS });
        cache.writeQuery({
          query: GET_TODOS,
          data: { todos: todos.concat([addTodo]) }
        });
      }}
    >
      {addTodo => (
        <div>
          <form
            onSubmit={e => {
              e.preventDefault();
              addTodo({ variables: { type: input.value } });
              input.value = "";
            }}
          >
            <input
              ref={node => {
                input = node;
              }}
            />
            <button type="submit">Add Todo</button>
          </form>
        </div>
      )}
    </Mutation>
  );
};

  第一步:我们从缓存中通过cache.readQurey读取相关的数据todos。

  第二步:我们将mutation生成的新的todo与第一步得到的todos连接在一起,并且通过writeQuery写回到对应的Qurey中。

现在我们的将会把我们新增的todo显示出来。

并不是所有的修改都需要update参数的,如果你仅需要更新一个item,那么你可以返回id和对应的属性,Apollo-client将会帮助你完成更新。

示例:

const UPDATE_TODO = gql`
  mutation UpdateTodo($id: String!, $type: String!) {
    updateTodo(id: $id, type: $type) {
      id
      type
    }
  }
`;

const Todos = () => (
  <Query query={GET_TODOS}>
    {({ loading, error, data }) => {
      if (loading) return <p>Loading...</p>;
      if (error) return <p>Error :(</p>;

      return data.todos.map(({ id, type }) => {
        let input;

        return (
          <Mutation mutation={UPDATE_TODO} key={id}>
            {updateTodo => (
              <div>
                <p>{type}</p>
                <form
                  onSubmit={e => {
                    e.preventDefault();
                    updateTodo({ variables: { id, type: input.value } });

                    input.value = "";
                  }}
                >
                  <input
                    ref={node => {
                      input = node;
                    }}
                  />
                  <button type="submit">Update Todo</button>
                </form>
              </div>
            )}
          </Mutation>
        );
      });
    }}
  </Query>
);

  

3、loading和error state

我们可以通过loading和error管理mutation的状态,此外还有called代表mutation function是否被调用了。

在Mutation组件上,还有onCompleted和onError等用于监视组件的行为。

4、Mutation api概览

utation组件接受以下props。只是mutation而且children必需的

mutation:DocumentNode
一个GraphQL变异文档解析为AST graphql-tag需要
children:( mutate:Function,result:MutationResult)=> React.ReactNode
一种允许您从UI触发变异的功能。需要
variables:{[key:string]:any}
包含您的突变需要执行的所有变量的对象
update:( cache:DataProxy,mutationResult:FetchResult)
用于在发生突变后更新缓存的函数
ignoreResults:布尔值
如果为true,则data渲染道具功能上属性不会随突变结果一起更新。
optimisticResponse:对象
在结果从服务器返回之前提供mutation result
refetchQueries:(mutationResult:FetchResult)=> Array <{query:DocumentNode,variables?:TVariables} | 字符串>
一个函数,允许您指定在发生突变后要重新获取的查询
awaitRefetchQueries:布尔值
作为一部分重新获取的查询refetchQueries是异步处理的,并且在变异完成(解决)之前不会等待。将此设置为true将确保在认为完成变异之前完成重新获取的查询。false默认。
onCompleted:(数据:TData)=>无效
一旦您的变异成功完成,就会执行回调
onError:(错误:ApolloError)=>无效
发生错误时执行的回调
context:记录<string,any>
Mutation组件与网络接口(Apollo Link)之间的共享上下文。用于从道具设置标题或将信息发送到requestApollo Boost 功能。
 

render prop 功能

渲染,你传递给道具功能children的道具Mutation被调用的mutate函数,并与mutation结果的对象。mutate功能是您从UI触发变异的方式。该对象包含您的变异结果,加上加载和错误状态。

变异功能:

mutate:(选项?:MutationOptions)=>承诺
用于从UI触发变异的函数。您可以选择通过variablesoptimisticResponserefetchQueries,和update作为选项,这将覆盖传递到任何道具Mutation组件。该函数返回一个履行变异结果的承诺。

变异结果:

data:TData
您的突变返回的数据。如果ignoreResults是真的,它可以是未定义的
loading:布尔值
一个布尔值,表示您的突变是否在飞行中
error:ApolloError
突变返回的任何错误
called:布尔值
一个布尔值,指示是否已调用mutate函数
client:ApolloClient
你的ApolloClient实例。用于在更新函数的上下文之外调用缓存方法,例如client.writeDataclient.readQuery

 全部代码:

const client = new ApolloClient({
  uri: "https://8v9r9kpn7q.lp.gql.zone/graphql"
});

const GET_TODOS = gql`
  {
    todos {
      id
      type
    }
  }
`;


const UPDATE_TODO = gql`
  mutation UpdateTodo($id: String!, $type: String!) {
    updateTodo(id: $id, type: $type) {
      id
      type
    }
  }
`;


const Todos = () => (
  <Query query={GET_TODOS}>
    {({ loading, error, data }) => {
      if (loading) return <p>Loading...</p>;
      if (error) return <p>Error :(</p>;

      return data.todos.map(({ id, type }) => {
        let input;
        return (
          <Mutation mutation={UPDATE_TODO} key={id}>
            {updateTodo =>(
              <div key={id}>
                <p>{type}</p>
                <form
                  onSubmit={e => {
                    e.preventDefault();
                    updateTodo({ variables: { id, type: input.value } });
                    // if (!input.value.trim()) {
                    //   return;
                    // }

                    input.value = "";
                  }}
                >
                  <input
                    ref={node => {
                      input = node;
                    }}
                  />
                  <button type="submit">Update Todo</button>
                </form>
              </div>
          );}
          </Mutation>
        );
      });
    }}
  </Query>
);

const ADD_TODO = gql`
  mutation AddTodo($type: String!) {
    addTodo(type: $type) {
      id
      type
    }
  }
`;


const AddTodo = () => {
  let input;

  return (
    <Mutation
      mutation={ADD_TODO}
      update={(cache, { data: { addTodo } }) => {
        const { todos } = cache.readQuery({ query: GET_TODOS });
        cache.writeQuery({
          query: GET_TODOS,
          data: { todos: todos.concat([addTodo]) }
        });
      }}
      >
      {(addTodo, { data }) => (
        <div>
          <form
            onSubmit={e => {
              e.preventDefault();
              addTodo({ variables: { type: input.value } });
              input.value = "";
            }}
          >
            <input
              ref={node => {
                input = node;
              }}
            />
            <button type="submit">Add Todo</button>
          </form>
        </div>
      )}
    </Mutation>
  );
};


const App = () => (
  <ApolloProvider client={client}>
    <div>
      <h2>Building Mutation components 🚀</h2>
      <AddTodo />
      <Todos />
    </div>
  </ApolloProvider>
);

ReactDOM.render(
    <App />,
   document.getElementById('root'));
registerServiceWorker();

  

posted @ 2018-08-25 16:18  tutu_python  阅读(731)  评论(0)    收藏  举报