React Apollo - странный эффект при мутации?

Я установил приложение React с React-Apollo и могу успешно запрашивать свой API.

Однако, когда я делаю мутацию, возникает странный эффект. Я успешно возвращаю все данные (как показано на вкладке «Сеть» в инструментах разработчика Chrome), но при попытке получить данные console.info он говорит, что это null.

Вот соответствующий код:

// mutation file

import gql from "graphql-tag";
export default gql`
  mutation CreateReservation($name: String!, $time: String!, $persons: String, $specialMessage: String, $email: String!) {
    createReservation(input: {
        name: $name,
        time: $time,
        persons: $persons,
        specialMessage: $specialMessage,
        email: $email
    }) {
        __typename
        error
        data
    }
  }
`;

// component file

import React from "react";
import {graphql, compose} from "react-apollo";
import CreateReservationMutation from "../../graphql/mutations/api/CreateReservation";

class Reservations extends React.Component {
testGraphQL = ({ reservationName, reservationTime, reservationEmail, reservationPartySize, reservationMessage}) => {

    const variables = {
        name: reservationName,
        time: reservationTime,
        persons: reservationPartySize,
        specialMessage: reservationMessage,
        email: reservationEmail
    };

    this.props.createReservation(variables)
    .then(({data}) => {
        console.info("Data received: ", data); // Here is the problem
    }).catch((err) => {
        console.info("Error sending data: ", err);
    })
}
render() {
    return (
        <div>
            ...
            <div>
                <Form 
                    ...
                    submitFunc = {this.testGraphQL}
                />
            </div>
            ...
            </div>
        </div>
    )
  }
}

export default compose(
    graphql(CreateReservationMutation, {
        props: ({mutate}) => ({
            createReservation: (variables) => mutate({variables})
        })
    })
)(Reservations);

Поэтому, когда я вызываю функцию testGraphQL, я получаю в консоли следующее:

Data received:  {createReservation: null}

Но глядя на вкладку «Сеть», я вижу, что данные все-таки там есть, и это именно то, что я ищу. Кроме того, моя база данных правильно обновлена ​​со всеми деталями бронирования, поэтому я точно знаю, что мутация выполняется.

Вот что я вижу на вкладке «Сеть»:

{"data":{"createReservation":{"__typename":"ReservationResponse","error":null,"data":"Success"}}}

Это то, что я ожидаю увидеть, когда назову console.info в testGraphQL.

Итак, я знаю, что у меня нет ошибок в моей схеме, моем клиенте Apollo или моем файле мутации.

Вместо этого проблема должна заключаться в том, как я настраиваю свой оператор compose или в том, как я вызываю саму мутацию.

Пожалуйста, дайте мне знать, если заметите здесь ошибку. Спасибо

ОБНОВИТЬ

Следует упомянуть, что я использую AWS AppSync в качестве поставщика GraphQL.

Мутация вызывает лямбда-функцию, которая выполняет следующие действия:

...
Promise.all([dynamodbPromise, snsPromise, sesPromise])
    .then((data) => {
        callback(null, {data: "Success"});
    })
    .catch((err) => {
        callback(null, {error: err});
    });

Вот мой преобразователь для этой мутации:

// request mapping template

{
  "version" : "2017-02-28",
  "operation": "Invoke",
  "payload": $util.toJson($ctx.args.input)
}

//  response mapping template

$util.toJson($context.result)

ОБНОВЛЕНИЕ 2

Настроил optimisticResonse и переписал мою мутацию следующим образом:

this.props.createReservation({
        variables,
        optimisticResponse: {
            createReservation: {
                __typename: "ReservationResponse",
                errorMessage: null,
                responseMessage: "_TEST_"
            }
        }
    })
    .then(res => {
        console.info("Apllo Data: ", res);
    })

Приводит меня к получению только данных из оптимистичного ответа, который заключается в следующем:

{data:
  createReservation: {
    __typename: "ReservationResponse", 
    errorMessage: null, 
    responseMessage: "Optimistic Success"
}

Таким образом, возвращаемые данные не должны обновляться фактическим ответом от API.

Как я могу теперь заставить Apollo обновить ответ после получения оптимистичного ответа?

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

Ответы 3

У вас есть два варианта получить ответ данных от мутации:

В компоненте Мутация:

<Mutation>{mutation, {data}}</Mutation>

Или в функции мутации:

mutate().then(data => ...)

Вы получаете ответ на обещание mutate, но ожидаете, что объект состояния будет передан apollo компоненту Mutation.

Для apollo не имеет смысла передавать объект состояния, потому что, если мутация разрешена, она была успешной, любая ошибка приведет к отклонению обещания, и во время вызова mutate состояние загрузки не предоставляется.

Итак, чтобы исправить ваш код, вам просто нужно изменить это

this.props.createReservation(variables)
    .then(data => {

Я изменил свой код, как вы предлагали, и получил сообщение об ошибке, что мои переменные не определены. Но согласно моему недавнему обновлению, я могу получить оптимистичные данные, и я думаю, что вы правы, что я получаю только объект состояния. Но я не понимаю, как это изменить, чтобы напрямую получать данные API. Вы можете объяснить, как я могу это сделать? Или дать ссылку на соответствующую документацию Apollo? я очень ценю это

Z_z_Z 13.10.2018 21:42

Я, наконец, решил это, хотя решение далеко не идеальное.

Мне пришлось написать функцию обновления для моей мутации. Это простая реализация, которая в конечном итоге дает мне фактические данные из API:

this.props.createReservation({
        variables,
        optimisticResponse: {
            createReservation: {
                __typename: "ReservationResponse",
                errorMessage: null,
                responseMessage: "Optimistic Success"
            }
        },
        update: (proxy, {data: {createReservation}}) => {
            console.info("Update: ", createReservation);
        }
    })
    .then(res => {
        console.info("Apllo Data: ", res);
    })

Функция обновления вызывается три раза. Первые два срабатывают до выполнения обещания и включают данные из optimisticResponse, как показано в моем разделе «Обновление 2». Наконец, третий вызов возвращает фактические данные из API.

Пока это будет работать, дайте мне знать, есть ли здесь более прямой метод. В этом случае я вообще не хочу возвращать optimisticResponse. Я хочу, чтобы возвращались только фактические данные из моего API. Таким образом, я могу дать своим пользователям правильную обработку ошибок в случае, если что-то пойдет не так.

Спасибо, и я надеюсь, что мы сможем помочь другим людям, у которых есть эта проблема.

вы можете получить доступ к возвращенным свойствам, просто используя res.data

this.props.createReservation({
    variables,
    optimisticResponse: {
        createReservation: {
            __typename: "ReservationResponse",
            errorMessage: null,
            responseMessage: "_TEST_"
        }
    }
})
.then(res => {
    console.info("Apllo Data: ", res.data);
})

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