Вызов Typescript Apollo Query из componentDidMount()

У меня есть компонент 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() и вызвать его как с каким-то способом «ожидания», чтобы он мог быть вызвана первой, а мутация после (и с использованием данных из запроса).

Спасибо, я знаю, что это не очень легко понять.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
2
0
1 724
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы ищете «старый» (используемый перед компонентом <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() и т. д. — просто добавив одну строку кода.

Можно ли использовать решение graphql(gql query ..." для загрузки валидаторов в componentDidMount(), чтобы массив мог быть сохранен и доступен в методе render()? Если да, не могли бы вы предоставить пример как это сделать?

Will de la Vega 27.05.2019 21:08

Спасибо, я понимаю, что шаблон HOC может быть не самой новой вещью, а также лично мне не очень нравится это решение, однако, поскольку в настоящее время, похоже, нет лучшего способа сделать это, то это было бы лучшим решение. возможно, однажды появится что-то вроде <Await><Query ...></Query></Await> Таким образом, код будет выглядеть намного чище, и нам не нужно будет тратить ресурсы на громоздкие шаблоны и структуры.

Will de la Vega 27.05.2019 23:11

Смешай это? Вы можете использовать компонент emhance с одним HOC для запроса (без составления) и использовать компонент <Mutation/> в render, если хотите. Шаблон Compose можно использовать с более сложными сценариями, полными жизненными циклами компонентов, дополнительными внутренними состояниями, обработчиками событий и т. д.

xadm 27.05.2019 23:24

Если вам нужен только shortcut, перезапишите render в 'QueryCustomerValidations/>` - визуализируйте условную загрузку (и ошибку) и визуализируйте дочерний элемент, когда данные будут готовы. Таким образом, вы можете просто обернуть свой <Mutation/> в одну строку.

xadm 27.05.2019 23:39

Другие вопросы по теме