Apollo / GraphQl - 单实体突变不更新缓存(数据库更新)

Posted

技术标签:

【中文标题】Apollo / GraphQl - 单实体突变不更新缓存(数据库更新)【英文标题】:Apollo / GraphQl - Single entity mutation does not update cache (database updated) 【发布时间】:2020-02-28 07:40:45 【问题描述】:

我在将 apollo / graphql 集成到新项目时遇到问题。

我有一个列出品牌的组件 BrandsList。在此组件中,您可以单击品牌以访问每个品牌的 updateForm 以更新其信息。

这是更新表格:

import React,  useState, useEffect  from "react";
import  graphql  from "react-apollo";
import gql from "graphql-tag";
import  UPDATE_BRAND  from "./../../../api/brands/mutations";
import  Form, Button, Dropdown, TextArea  from "semantic-ui-react";
import  useQuery, useMutation  from "@apollo/react-hooks";

const brandQuery = gql`
    query Brand($brandId: String) 
        brand(_id: $brandId) 
            _id
            name
            url
            description
            brandType
            openingDate
            closingDate
            origin
            region
            address
        
    
`;

const UpdateBrand = props => 
    const [values, setValues] = useState(
        _id: "",
        name: "",
        url: "",
        description: "",
        origin: "",
        region: "",
        brandType: "",
        openingDate: "",
        closingDate: "",
        address: ""
    );

    const onChange = e => 
        const  name, value  = e.target;
        setValues( ...values, [name]: value );
    ;

    const  loading, error, data, refetch  = useQuery(brandQuery, 
        variables:  brandId: props.match.params.brandId 
    );

    useEffect(() => 
        if (data) 
            setValues( ...data.brand );
        
    , [data]);

    const [updateBrand,  brand ] = useMutation(UPDATE_BRAND);

    const onChangeDropDown = (e,  value ) =>
        setValues( ...values, brandType: value );

    const onSubmit = e => 
        e.preventDefault();
        let 
            _id,
            name,
            url,
            description,
            origin,
            region,
            brandType,
            openingDate,
            closingDate,
            address
         = values;

        updateBrand(
            variables: 
                brandId: _id,
                name,
                url,
                description,
                origin,
                region,
                brandType,
                openingDate,
                closingDate,
                address
            
        )
        .then(() => props.history.push("/admin/brands"))
        .catch(err => console.log(err));

    ;


    return (
        <div className="createBrand">
            <h1>Add a Brand</h1>
            /* BORING STATE CONTROLLED FORM  */
                <Button type="submit" form="createBrandForm">
                    Update
                </Button>
            </Form>
        </div>
    );
;

export default UpdateBrand;

通常它运行良好,不确定使用 useEffect 将查询结果带到我的本地状态是否是最有效的,但它有效。我可以修改我的表单并重新提交它,并且数据库中的数据已更改。但是,当我通过 props.history.push 回到 /admin/brands 时,数据没有更新,我必须进行一次硬刷新。

我的变异解析器是这样的:

updateBrand(obj, args, context) 
    if (!context.user || !context.user.isAdmin) 
        throw new Error("You have to be an admin to update a brand");
     else if (context.user.isAdmin) 
        let 
            brandId,
            name,
            url,
            description,
            origin,
            region,
            brandType,
            openingDate,
            closingDate,
            address
         = args;
        Brands.update(
             _id: brandId ,
            
                $set: 
                    name,
                    url,
                    description,
                    origin,
                    region,
                    brandType,
                    openingDate,
                    closingDate,
                    address
                
            
        );
        return Brands.findOne( _id: brandId );
    
,

因此,根据文档,我将返回更新后的单个对象,该对象应强制更新缓存以修改单个实体。然而事实并非如此。关于如何在每次修改后更新数据的任何想法?

这里是突变代码:

export const UPDATE_BRAND = gql`
    mutation updateBrand(
        $brandId: String!
        $name: String!
        $url: String
        $description: String
        $origin: String
        $region: String
        $brandType: String
        $openingDate: String
        $closingDate: String
        $address: String
    ) 
        updateBrand(
            brandId: $brandId
            name: $name
            url: $url
            description: $description
            origin: $origin
            region: $region
            brandType: $brandType
            openingDate: $openingDate
            closingDate: $closingDate
            address: $address
        ) 
            _id
        
    
`;

这里是架构部分:

type Mutation 
    createBrand(
        name: String!
        url: String
        description: String
        origin: String
        region: String
        brandType: String
        openingDate: String
        closingDate: String
        address: String
    ): Brand
    updateBrand(
        brandId: String!
        name: String!
        url: String
        description: String
        origin: String
        region: String
        brandType: String
        openingDate: String
        closingDate: String
        address: String
    ): Brand
    deleteBrand(brandId: String!): Boolean

【问题讨论】:

能否包含更新突变的 GraphQL 查询代码。这可能是了解您的查询可能不会更新的原因的最重要的一段代码。我刚刚解释了 Apollo 如何更新 this question 中的查询。 @Herku 感谢您花时间检查。刚刚更新了我的问题。将检查您提到的帖子。 @Herku 实际上你的问题让我意识到我的错误。在突变 graphql 中,我只要求从查询中返回更新的 _id,而我应该要求返回完整的数据。 【参考方案1】:

我的错误在于我的 graphQL 查询代码中的更新突变,正如@Herku 所建议的那样。我只是在更新后发回 _id 而不是其余的数据。更改为以下解决了该问题:

export const UPDATE_BRAND = gql`
    mutation updateBrand(
        $brandId: String!
        $name: String!
        $url: String
        $description: String
        $origin: String
        $region: String
        $brandType: String
        $openingDate: String
        $closingDate: String
        $address: String
    ) 
        updateBrand(
            brandId: $brandId
            name: $name
            url: $url
            description: $description
            origin: $origin
            region: $region
            brandType: $brandType
            openingDate: $openingDate
            closingDate: $closingDate
            address: $address
        ) 
            _id
            name
            url
            description
            origin
            region
            brandType
            openingDate
            closingDate
            address
        
    
`;

【讨论】:

【参考方案2】:

列表查询必须手动更新:

https://www.apollographql.com/docs/react/data/mutations/#making-all-other-cache-updates

【讨论】:

以上是关于Apollo / GraphQl - 单实体突变不更新缓存(数据库更新)的主要内容,如果未能解决你的问题,请参考以下文章

既不是突变也不是查询的 Apollo/GraphQL 动作

Apollo GraphQL 突变结果不使用 PostgreSQL 更新,但适用于 SQLite

删除突变后不重新获取查询(Apollo Graphql & Nextjs)

Apollo GraphQL 嵌套突变

Apollo / GraphQL / Prisma“登录”突变不会返回所有用户字段

为嵌套模式 graphql/apollo/react 添加突变