从componentDidMount()调用Typescript Apollo查询

时间:2019-05-27 08:08:03

标签: reactjs typescript react-apollo apollo-client react-tsx

我有一个React组件,该组件调用一个查询,该查询期望接收一个对象数组(用于验证数据),然后我使用该对象来验证依次由apollo Mutation元素定义的html表单,即构造在组件render()方法的return语句中的结构可以工作,但看起来很麻烦,它使我想起了回调地狱时代。我真正想做的是摆脱render()方法中的<QueryCustomerValidations>元素,并将其移入(理想情况下)componentDidMount生命周期事件中,以便可以将验证器加载到那里以便以后在表单中使用,然后将<MutationCreateCustomer>留在render()中。

现在,我必须将表格包装在突变内部,查询返回的箭头函数内部的变异,以便以正确的顺序接收异步数据。请看一下它的外观

    //-------------------------------------------------------------------------
    // Component Lifecycle Eventhandler Methods
    //-------------------------------------------------------------------------
    componentDidMount()
    {

    }    


    //-------------------------------------------------------------------------
    // Render Method Section
    //-------------------------------------------------------------------------
    public render(): JSX.Element
    {
        // Return Form
        return (
            <React.Fragment>
                {/* PAGE TITLE  */}
                <h2 className="text-center mb-3">Agregar Nuevo Cliente</h2>

                {/* LOAD VALIDATIONS INTO STATE  */}
                <QueryCustomerValidations
                    query={Q_GET_CUSTOMER_VALIDATIONS}
                >
                    {({ loading: loadingValidations, error: errorValidations, data: dataValidations }) =>
                    {
                        if (loadingValidations)
                        {
                            return "Cargando..."
                        }
                        if (errorValidations)
                        {
                            return `Error: ${errorValidations.message}`
                        }
                        if (dataValidations)
                        {
                            const validators: ValidationDescriptor[] = []
                            dataValidations.getCustomerValidations.forEach((validator) => {
                                validators.push(validator as ValidationDescriptor)
                            })
                            this.validators.setValidators(validators)
                        }

                        /* DATA ENTRY FORM  */
                        return (
                            <div className="row justify-content-center">

                                <MutationCreateCustomer 
                                    mutation={M_CREATE_CUSTOMER}
                                    onCompleted={() => this.props.history.push('/')}
                                >
                                    {(createCustomer: any) => {
                                        return (                                            
                                            <form name="frmNewCustomer"
                                                    className="col-md-8 m-3"
                                                    onSubmit={e => this.frmNewCustomer_submit(e, createCustomer)}
                                            >

                                                { this.ctrl_form_layout(this.props, this.state, this.validators) }

                                            </form>
                                        )
                                    }}
                                </MutationCreateCustomer>
                            </div>
                        )
                    }}

                </QueryCustomerValidations>

            </React.Fragment>
        );
    }

出于文档目的,这里是创建查询的接口。由于我使用apollo cli从服务器上获得了一些数据,因此在这种情况下,onDidMount()上的简单graphql查询解决方案将无法工作。

getCustomerValidations.ts (Interfaces)


// ====================================================
// GraphQL query operation: getCustomerValidations
// ====================================================

export interface getCustomerValidations_getCustomerValidations {
  __typename: "ValidationDescriptor";
  field: string | null;
  type: string | null;
  required: boolean;
  max: number | null;
  min: number | null;
  regex: string | null;
}

export interface getCustomerValidations {
  getCustomerValidations: getCustomerValidations_getCustomerValidations[];
}

customer-validations.query.ts (Client side query types)


//---------------------------------------------------------------------------------
// Imports Section (React/Apollo Libs)
//---------------------------------------------------------------------------------
import { gql }                              from 'apollo-boost';
import { Query }                            from 'react-apollo'

import { getCustomerValidations }            from '../../typeDefs/operations/getCustomerValidations'

//---------------------------------------------------------------------------------
// GQL Query: Customers
//---------------------------------------------------------------------------------
export const Q_GET_CUSTOMER_VALIDATIONS = gql`
    query getCustomerValidations {
        getCustomerValidations
        {
            field
            type
            required
            max
            min
            regex
        }
    }
`;

//---------------------------------------------------------------------------------
// Query Class: Customers
//---------------------------------------------------------------------------------
export class QueryCustomerValidations extends Query<getCustomerValidations> { }


正确的解决方案可以是从componentDidMount()方法复制并触发<QueryCustomerValidations>元素的一种方法,也可以是如何从render()方法中删除元素并像进行某种调用一样调用它“等待”的方式,因此可以先调用它,然后再调用它(并使用查询中的数据)。

谢谢,我知道这真的很难弄清楚。

1 个答案:

答案 0 :(得分:2)

您正在寻找描述hereherehere的“旧”(在<Query/>组件之前使用)HOC模式(带有compose)。

在开始时请求的“ graphql(gql query ...”(不带条件的skip选项)与一个或多个(命名为)“ gql mutation ...”(按需调用)组成清晰易读的解决方案。

compose(
  graphql(Q_GET_CUSTOMER_VALIDATIONS),
  graphql(gql`mutation { ... }`, { name: 'createSth' })
)(SomeComponent)

datacreateSth道具传递给<SomeComponent/>,然后this.props.data对象将包含loadingerrorgetCustomerValidations字段/ properties。描述为here

查询将在开始时调用(您可以期望true中的this.props.data.loading),而无需在cDM()处运行查询。可以使用this.props.createSth()-上面定义的自定义名称(而不是默认的道具名称mutate)来运行突变。

当然,您可以将它们与其他必需的HOC混合使用,例如redux connect()withFormik()等-只需添加一行代码即可。