开发者问题收集

如何:在 GraphQL 中增加整数字段的值

2017-03-29
5693

因此,我希望在 GraphCool 中创建一个 GraphQL 突变,将整数字段的现有值增加预定量,作为变量传入。例如:

mutation updateLikes ($id: ID!, $count: Int) {
  updatePosts (id: $id, likes: incrementBy $count) {
    id
    likes
  }
}

Query variable

{
  "id" : "cj0qkl04vep8k0177tky596og",
  "count": 1
}

我该怎么做?

此外,我试图从 onClick 事件触发上述过程,但收到“无法读取属性‘props’为 null”的错误消息,我怀疑是 this.props.client.query 的问题:

Photo.js

import React from 'react';
import Comments from './Comments';
import CSSTransitionGroup from 'react-addons-css-transition-group';
import { Link } from 'react-router';
import {
  gql,
  graphql,
  withApollo
} from 'react-apollo';
import ApolloClient from 'apollo-client';

class Photo extends React.Component {

  incrementQuery(currentID) {
    console.log("like of id=" + currentID+ " has been incremented by 1");

    this.props.client.query({
      query: gql`
        mutation updatePosts($id: ID!) {
          updatePosts (id: $id, likes: 1) {
            id
            likes
          }
        }  
      `,
      variables: {
        id: currentID,
      },
    });
  }

  render() {
    const { post, i } = this.props;

    return (
      <figure key={i} className="grid-figure">

        <div className='grid-photo-wrap'>
          <Link to={`/view/${post.id}`}>
            <img className='grid-photo' src={post.displaysrc} alt={post.caption} />
          </Link>

          <CSSTransitionGroup transitionName="like" transitionEnterTimeout={500} transitionLeaveTimeout={500}>
            <span key={post.likes} className="likes-heart">{post.likes}</span>
          </CSSTransitionGroup>

        </div>

        <figcaption>
          <p>{post.caption}</p>

          <div className="control-buttons">
            <button onClick={this.incrementQuery.bind(null,i)} className="likes">&hearts; {post.likes}</button>

            <Link to={`/view/${post.id}`} className="button">
              <span className="comment-count">
                <span className="speech-bubble"></span> {(post.comments ? Object.keys(post.comments).length : 0)}
              </span>
            </Link>
          </div>

        </figcaption>

      </figure>
    )
  }
};

Photo.PropTypes = {
  client: React.PropTypes.instanceOf(ApolloClient).isRequired,
  query: React.PropTypes.object,
  variables: React.PropTypes.object,
  data: React.PropTypes.shape({
    loading: React.PropTypes.bool.isRequired,
    error: React.PropTypes.bool.isRequired,
    updatePosts: React.PropTypes.object,
  }).isRequired,
}

const PhotoWithApollo = withApollo(Photo);

export default PhotoWithApollo;

抛出的错误如下:

Uncaught TypeError: Cannot read property 'props' of null
    at incrementQuery (http://localhost:7770/static/bundle.js:56347:12)
    at proxiedMethod (http://localhost:7770/static/bundle.js:54898:31)
    at HTMLUnknownElement.wrapped (http://localhost:7770/static/bundle.js:47347:30)
    at Object.ReactErrorUtils.invokeGuardedCallback (http://localhost:7770/static/bundle.js:6346:17)
    at executeDispatch (http://localhost:7770/static/bundle.js:6146:22)
    at Object.executeDispatchesInOrder (http://localhost:7770/static/bundle.js:6169:6)
    at executeDispatchesAndRelease (http://localhost:7770/static/bundle.js:5599:23)
    at executeDispatchesAndReleaseTopLevel (http://localhost:7770/static/bundle.js:5610:11)
    at Array.forEach (native)
    at forEachAccumulated (http://localhost:7770/static/bundle.js:6446:10)
    at Object.processEventQueue (http://localhost:7770/static/bundle.js:5815:8)
    at runEventQueueInBatch (http://localhost:7770/static/bundle.js:6475:19)
    at Object.handleTopLevel [as _handleTopLevel] (http://localhost:7770/static/bundle.js:6491:6)
    at handleTopLevelWithoutPath (http://localhost:7770/static/bundle.js:16697:25)
    at handleTopLevelImpl (http://localhost:7770/static/bundle.js:16677:4)
    at ReactDefaultBatchingStrategyTransaction.perform (http://localhost:7770/static/bundle.js:8643:21)
    at Object.batchedUpdates (http://localhost:7770/static/bundle.js:12680:20)
    at Object.batchedUpdates (http://localhost:7770/static/bundle.js:8148:21)
    at dispatchEvent (http://localhost:7770/static/bundle.js:16808:21)
    at HTMLDocument.wrapped (http://localhost:7770/static/bundle.js:47347:30)
3个回答

目前您需要先查询该值:

query Post($id: ID!) {
  Post (id: $id) {
    id
    likes
  }
}

然后在客户端增加 likes ,并使用 likes 的新值更新帖子:

mutation updateLikes ($id: ID!, $likes: Int!) {
  updatePost (id: $id, likes: $likes) {
    id
    likes
  }
}

通过特殊数字增加点赞是 自定义突变 的一个很好的用例,我们已经在研究它了。

marktani
2017-03-29

对于 AWS 用户,我个人也遇到过同样的问题,即会计系统。读取然后更新值的风险在于,如果多个用户调用您的脚本,可能会发生一些并发问题。(用户可以在另一个用户更新当前值之前读取当前值,因此他将引发其他用户增量)。 我所做的是:

  1. 创建一个队列请求表,我明确写入我想要增加我的变量。
  2. 创建一个在该表事件上触发的 lambda(此 lambda 将在任何时候在此表中发生某事时触发)
  3. 将此 lambda 并发性限制为 1,以避免读取正在更改的值
  4. 从请求队列表中读取值,增加我的最后一个元素并从队列表中删除请求队列。所有这些都必须在您刚刚创建的唯一并发 lambda 中完成。
vince
2022-06-13

是的,这个问题很有意思,其实 Apollo 客户端也是用同样的方法处理分页的,必须先获取当前页,然后到页面底部,( 上一页+1 )=>( 下一页 ) 生成一个新的页面变量,获取下一页内容,然后连接到上一页。dislike/like,方法相同,区别在于不需要连接到上一页。替换即可。

Zhang Yung
2018-01-18