I have a React Component that calls a Query that expects to receive an array of objects (for validation data). I then use it to validate an html form, that is in turn defined inside of an apollo Mutation element. The way it is structured within the return statement of the component render()
method works but it looks cumbersome and it reminds me of the callback hell era. What I really want to do is to get rid of the <QueryCustomerValidations>
element in the render()
method and move it into (ideally) the componentDidMount
lifecycle event. So that the validators can be loaded there for later use within the form, then leave the <MutationCreateCustomer>
inside render().
Right now, I have to wrap the form inside the mutation. The mutation inside the arrow function that the query returns in order to receive the async data in the proper order.
//-------------------------------------------------------------------------
// 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>
);
}
Here for documentation purposes are the interfaces to create the Query. Since I get some of this data from the server using the apollo client, a simple graphql query solution on the onDidMount()
would not work in this case.
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> { }
The right solution can be a way to copy -and trigger- the <QueryCustomerValidations>
element from the componentDidMount()
method or, how to take the element away from the render()
method and call it like with some sort of "await" way of doing it so it can be called first and the mutation after (and using the data from the query).
Thanks, I know this one is not really easy to figure out.