Я установил приложение 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 обновить ответ после получения оптимистичного ответа?





У вас есть два варианта получить ответ данных от мутации:
В компоненте Мутация:
<Mutation>{mutation, {data}}</Mutation>
Или в функции мутации:
mutate().then(data => ...)
Вы получаете ответ на обещание mutate, но ожидаете, что объект состояния будет передан apollo компоненту Mutation.
Для apollo не имеет смысла передавать объект состояния, потому что, если мутация разрешена, она была успешной, любая ошибка приведет к отклонению обещания, и во время вызова mutate состояние загрузки не предоставляется.
Итак, чтобы исправить ваш код, вам просто нужно изменить это
this.props.createReservation(variables)
.then(data => {
Я, наконец, решил это, хотя решение далеко не идеальное.
Мне пришлось написать функцию обновления для моей мутации. Это простая реализация, которая в конечном итоге дает мне фактические данные из 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);
})
Я изменил свой код, как вы предлагали, и получил сообщение об ошибке, что мои переменные не определены. Но согласно моему недавнему обновлению, я могу получить оптимистичные данные, и я думаю, что вы правы, что я получаю только объект состояния. Но я не понимаю, как это изменить, чтобы напрямую получать данные API. Вы можете объяснить, как я могу это сделать? Или дать ссылку на соответствующую документацию Apollo? я очень ценю это