首页 > 解决方案 > Apollo:Push() 方法导致组件在 Mutation 中的乐观响应更新时卸载

问题描述

任何人都可以猜测以下乐观响应/更新代码的原因(代码后问题继续存在):

AddToCart.js

const ADD_TO_CART_MUTATION = gql`
  mutation addToCart($id: ID!) {
    addToCart(id: $id) {
      id
      quantity
    }
  }
`;

class AddToCart extends React.Component {
  outOfStock(){
    alert('This item is out of stock.');
  };
  
  update = (cache, { data: { addToCart } }) => {
    const data = cache.readQuery({ query: CURRENT_USER_QUERY });
    data.me.cart.push(addToCart);
    cache.writeQuery({ query: CURRENT_USER_QUERY, data });
  };
  
  render() {
    const { id, quantity, title, image, price } = this.props;
    return (
      <Mutation
        mutation={ADD_TO_CART_MUTATION}
        variables={{
          id,
        }}
        optimisticResponse={{
          __typename: 'Mutation',
          addToCart: {
            __typename: 'CartItem',
            id: '-1',
            quantity: 1,
            item: {
              __typename: 'Item',
              id,
              price,
              image,
              title,
              description: 'test',
              mainDescription: 'test',
              quantity,
            }
          }
        }}
        update={this.update}
        refetchQueries={[{ query: CURRENT_USER_QUERY }, { query: ALL_ITEMS_QUERY }]}
      >
        {(addToCart, { loading }) => {
          if (quantity >= 1) {
            return (<button disabled={loading} onClick={() => {
              addToCart().catch(err => alert(err.message));
            }}>
              Add{loading && 'ing'} To Cart 
            </button>)
          } else {
            return (<button>
              Out of Stock 
            </button>)
          }
        }}
      </Mutation>
    );
  }
}

export default AddToCart;

AddToCart 父组件 (Item.js)

export default class Item extends Component {
  static propTypes = {
    item: PropTypes.object.isRequired,
  };

  render() {
    const { item } = this.props;
    return (
      <User>
        {({ data: { me } }) => {
          let hasPerms;
          hasPerms = (me && me === null) ? false : (me && me.permissions.some(permission => ['ADMIN'].includes(permission)));
          return (
          <ItemStyles>
            {item.image && <img src={item.image} alt={item.title} />}
            <Title>
              <Link
                href={{
                  pathname: '/item',
                  query: { id: item.id },
                }}
              >
                <a>{item.title}</a>
              </Link>
            </Title>
            <PriceTag>{formatMoney(item.price)}</PriceTag>
            <p>{item.description} { (item.quantity <= 10 && item.quantity !== 0) && `- (${item.quantity} in stock)` }</p>
            <div className="buttonList">
              <AddToCart id={item.id} quantity={item.quantity} image={item.image} title={item.title} price={item.price} />
              {hasPerms && (
              <>
              <Link
                href={{
                  pathname: 'update',
                  query: { id: item.id },
                }}
              >
                <a>Edit ✏️</a>
              </Link>
              <DeleteItem id={item.id}>Delete This Item</DeleteItem>
              </>
              )}
            </div>
            <div className="buttonList">
            </div>
          </ItemStyles>
          );
        }}
      </User>
    );
  }
}

项父项 (Items.js)

class Items extends Component {
  render() {
    return (
      <Center>
        <Pagination page={this.props.page} />
        <Query
          query={ALL_ITEMS_QUERY}
          variables={{
            skip: this.props.page * perPage - perPage,
          }}
        >
          {({ data, error, loading }) => {
            if (loading) return <p>Loading...</p>;
            if (error) return <p>Error: {error.message}</p>;
            return (
              <ItemsList>{data.items.map((item, i) => <Item item={item} key={item.id}></Item>)}</ItemsList>
            );
          }}
        </Query>
        <Pagination page={this.props.page} />
      </Center>
    );
  }
}

export default Items;

将项目添加到空购物车后导致我的 UI 重新呈现(组件卸载)(请参阅复制说明)?

  1. 转到https://flamingo-next-production.herokuapp.com
  2. 登录使用,用户名:testing123@123.com,密码:testing123
  3. 单击“我的购物车”链接并删除其中的所有项目。保持购物车窗口打开。
  4. 单击Shop链接并添加一个项目。单击添加后观察打开的购物车窗口/UI(您可能需要等待片刻才能观察到变化)。

为什么会发生这种情况以及纠正它的最佳方法是什么?

标签: reactjsgraphqlapolloapollo-client

解决方案


推荐阅读