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

#reactjs #apollo-client

#реагирует на #аполлон-клиент

Вопрос:

Реактивные переменные имеют большой смысл при хранении простых скалярных значений, но если вам нужно иметь дело с более сложным состоянием (скажем, ID-gt;object картой), вы столкнетесь с проблемами производительности рендеринга. Проблема в том, что реактивные переменные фактически неизменяемы: вы не можете просто изменить какое-то под-свойство переменной и ожидать, что оно будет реагировать правильно; вам нужно указать совершенно новое значение для переменной. Но тогда каждый компонент, который прослушивает эту переменную, будет перенаправляться, даже если многим из них может быть наплевать на это конкретное свойство.

Я поясню это на примере. Допустим, у меня есть эта реактивная переменная:

 const itemsMapVar = makeVar({  item1: { text: "Text 1" },  item2: { text: "Text 2" } })   

И я представляю список элементов, каждый из которых выглядит следующим образом:

 const ListItem = (props) =gt; {  const item = useReactiveVar(itemsMapVar)[props.id];  return lt;divgt;{item.text}lt;/divgt; }  

Предположим, я изменю текст для пункта 1:

 itemsMapVar({  ...itemsMapVar(),  item1: { text: 'New text' } })  

Теперь и пункт 1, и пункт 2 будут повторяться, потому что они оба слушают itemsMapVar . Это может не быть проблемой в этом тривиальном примере, но если есть длинный список элементов с большим количеством DOM, это будет проблемой. Существует ли устоявшаяся передовая практика для решения этой проблемы?

Некоторые варианты, которые я рассмотрел:

  • Используйте другую библиотеку состояний клиента. Что-то вроде Redux или MobX легко решает такого рода проблемы. Одним большим недостатком является то, что я не могу использовать это состояние как часть реактивного запроса GraphQL, и, вероятно, именно поэтому я в первую очередь использую Apollo.
  • Поместите компонент обертки lt;ListItemgt; , содержащий useReactiveVar крючок, и извлеките свойство, которое меня интересует. Тогда React.memo включение ListItem предотвратит его ненужный рендеринг. Это не страшно; но вы все равно визуализируете O(N) элементов, но это всего лишь легкие элементы обертки. И это кажется довольно многословным и неуклюжим для того, что кажется обычной проблемой при работе с состоянием клиента.
  • Придумайте какую-нибудь новую версию useReactiveVar , которая знает, как выбрать нужную вам часть состояния, похожую на Redux useSelector . (Существует ли такая вещь уже?)