Подтвердить что ты не робот

Как определить состояние загрузки мутации с помощью реакции-apollo graphql

Обновление 2018: Клиент Apollo 2.1 добавил новый компонент Mutation, который добавляет свойство загрузки обратно. См. Ответ @robin-wieruch ниже и объявление здесь https://dev-blog.apollodata.com/introduction-react-apollo-2-1-c837cc23d926 Читайте оригинальный вопрос, который теперь применим только к более ранним версиям Apollo.


Используя текущую версию graphql более высокого порядка graphql в graphql react-apollo (v0.5.2), я не вижу документированного способа информирования моего пользовательского интерфейса о том, что мутация ожидает ответа сервера. Я вижу, что более ранние версии пакета отправляли свойство, указывающее загрузку.

Запросы по-прежнему получают свойство загрузки, как описано здесь: http://dev.apollodata.com/react/queries.html#default-result-props

Мое приложение также использует избыточность, поэтому я думаю, что один из способов сделать это - подключить мой компонент к избыточности и передать свойство функции, которое переведет мой пользовательский интерфейс в состояние загрузки. Затем, когда я переписываю свою мутацию graphql в свойство, я могу сделать вызов, чтобы обновить хранилище избыточности.

Примерно так:

function Form({ handleSubmit, loading, handleChange, value }) {
  return (
    <form onSubmit={handleSubmit}>
      <input
        name="something"
        value={value}
        onChange={handleChange}
        disabled={loading}
      />
      <button type="submit" disabled={loading}>
        {loading ? 'Loading...' : 'Submit'}
      </button>
    </form>
  );
}

const withSubmit = graphql(
  gql'
    mutation submit($something : String) {
      submit(something : $something) {
        id
        something
      }
    }
  ', 
  {
    props: ({ ownProps, mutate }) => ({
      async handleSubmit() {
        ownProps.setLoading(true);
        try {
          const result = await mutate();
        } catch (err) {
          // @todo handle error here
        }
        ownProps.setLoading(false);
      },
    }),
  }
);

const withLoading = connect(
  (state) => ({ loading: state.loading }),
  (dispatch) => ({
    setLoading(loading) {
      dispatch(loadingAction(loading));
    },
  })
);

export default withLoading(withSubmit(Form));

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

4b9b3361

Ответ 1

Я повторно разместил этот вопрос на github, и предлагаемое решение заключалось в том, чтобы использовать что-то вроде реагирующего компонента более высокого порядка так же, как вы предлагали в вашем первоначальном вопросе. Я сделал аналогичную вещь - без использования сокращения, но - как указано в этом вопросе.

Чтобы привести Tom Coleman ответ от проблемы github:

На самом деле нет смысла включать состояние загрузки в мутацию контейнер; если вы думаете об этом, вы можете дважды вызвать мутацию одновременно - какое состояние загрузки должно передаваться ребенку? мой ощущение вообще нехорошо смешивать императив (this.mutate(x, y, z)) с декларативными (реквизитами) вещами; это приводит к неразрешимым несоответствиям.

Ответ 2

Любой, кто сталкивается с этим вопросом, начиная с Apollo Client 2.1, вы имеете доступ к этим свойствам в функции рендеринга реквизитов компонента Query and Mutation.

import React from "react";
import { Mutation } from "react-apollo";
import gql from "graphql-tag";

const TOGGLE_TODO = gql'
  mutation ToggleTodo($id: Int!) {
    toggleTodo(id: $id) {
      id
      completed
    }
  }
';

const Todo = ({ id, text }) => (
  <Mutation mutation={TOGGLE_TODO} variables={{ id }}>
    {(toggleTodo, { loading, error, data }) => (
      <div>
        <p onClick={toggleTodo}>
          {text}
        </p>
        {loading && <p>Loading...</p>}
        {error && <p>Error :( Please try again</p>}
      </div>
    )}
  </Mutation>
);

Примечание. Пример кода взят из публикации блога Apollo Client 2.1.