У меня есть компонент React, который вызывает запрос, который ожидает получить массив объектов (для данных проверки). Затем я использую его для проверки html-формы, которая, в свою очередь, определена внутри элемента мутации apollo. То, как он структурирован в операторе return метода компонента render(), работает, но выглядит громоздко и напоминает мне эпоху ада колбэков. Что я действительно хочу сделать, так это избавиться от элемента <QueryCustomerValidations> в методе render() и переместить его (в идеале) в событие жизненного цикла 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, простое решение запроса graphql на onDidMount() в этом случае не сработает.
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> { }
Правильным решением может быть способ скопировать и активировать элемент <QueryCustomerValidations> из метода componentDidMount() или как убрать элемент из метода render() и вызвать его как с каким-то способом «ожидания», чтобы он мог быть вызвана первой, а мутация после (и с использованием данных из запроса).
Спасибо, я знаю, что это не очень легко понять.





Вы ищете «старый» (используемый перед компонентом <Query/>) шаблон HOC (с compose), описанный здесь, здесь и здесь.
Составление «graphql(gqlquery ...», запрошенного при запуске (без условной опции skip) с одним или несколькими (именованными) «gqlmutation ...» (вызывается по запросу) дает вам четкое, удобочитаемое решение.
compose(
graphql(Q_GET_CUSTOMER_VALIDATIONS),
graphql(gql`mutation { ... }`, { name: 'createSth' })
)(SomeComponent)
передаст реквизиты data и createSth в <SomeComponent/>, тогда объект this.props.data будет содержать поля/свойства loading, error и getCustomerValidations. Описано здесь.
Запрос будет вызываться при запуске (вы можете ожидать true в this.props.data.loading), нет необходимости запускать запрос в cDM(). Мутация может быть запущена с использованием this.props.createSth() - пользовательского имени, определенного выше (вместо имени свойства по умолчанию mutate).
Конечно, вы можете смешивать их с другими необходимыми HOC, например. redux connect(), withFormik() и т. д. — просто добавив одну строку кода.
Спасибо, я понимаю, что шаблон HOC может быть не самой новой вещью, а также лично мне не очень нравится это решение, однако, поскольку в настоящее время, похоже, нет лучшего способа сделать это, то это было бы лучшим решение. возможно, однажды появится что-то вроде <Await><Query ...></Query></Await> Таким образом, код будет выглядеть намного чище, и нам не нужно будет тратить ресурсы на громоздкие шаблоны и структуры.
Смешай это? Вы можете использовать компонент emhance с одним HOC для запроса (без составления) и использовать компонент <Mutation/> в render, если хотите. Шаблон Compose можно использовать с более сложными сценариями, полными жизненными циклами компонентов, дополнительными внутренними состояниями, обработчиками событий и т. д.
Если вам нужен только shortcut, перезапишите render в 'QueryCustomerValidations/>` - визуализируйте условную загрузку (и ошибку) и визуализируйте дочерний элемент, когда данные будут готовы. Таким образом, вы можете просто обернуть свой <Mutation/> в одну строку.
Можно ли использовать решение graphql(gql query ..." для загрузки валидаторов в componentDidMount(), чтобы массив мог быть сохранен и доступен в методе render()? Если да, не могли бы вы предоставить пример как это сделать?