Как лучше всего ограничить количество одновременных запросов (клиент Apollo GraphQL) при использовании хуков useMutation? - PullRequest
0 голосов
/ 04 августа 2020

Следующий компонент React представляет собой форму, которая позволяет пользователю одновременно обновлять сотни записей. Чтобы сохранить масштабируемость сервера, я решил следовать рекомендациям в этом посте, библиотеке pLimit, чтобы ограничить количество одновременных запросов, попадающих на сервер: Каков наилучший способ ограничить параллелизм при использовании ES6 Promise.all ( )? .

Однако я не смог обойти эти две ошибки:

  1. Обработано больше хуков, чем во время предыдущего рендеринга
  2. Хуки могут только быть вызванным внутри тела функционального компонента

Я попытался использовать хуки useMutation для вызова мутации для каждой записи. Проблема в том, что у меня не может быть хука useMutation в функции в оболочке pLimit Promise, если эта функция не является компонентом. Но я не могу сделать эту функцию компонентом, иначе я столкнусь со второй ошибкой выше.

Итак, я пытался найти решение этой проблемы.

  1. https://www.apollographql.com/docs/react/api/link/apollo-link-batch-http/#options
  2. Имейте состояние React словаря, которое постепенно обновляется параллельными вызовами updateIndividual, ограниченным pLimit.
import pLimit from 'p-limit'

function updateIndividual(x) {
  let [update, {called, loading, error}] = useMutation(UpdateMutation, {
    client: client,
    variables: {...},
  });
  update()
  let label = x.name + " ";
  label += loading ? "updating..." : error ? `error... ${error}` : called ? "updated" : "start";
  return label
}

export default function Form(props) {
  const [rows, setRows] = useState(props.data.reduce(function(map, val) {
    map[val] = undefined;  // { 'one': undefined, 'two': undefined...}
    return map;
  }, {}));

  const limit = pLimit(3);
  const promises = data?.map(x => {
    return limit(() => updateIndividual(x));
  });

  (async () => {
    setRows(await Promise.all(promises));
  })();

  return <div id='update-rows'>
  {rows.map((k, v) => (
    <div id={k}>{rows}</div>
  ))}
</div>
}
...