Итак, я использую Apollo-link-state для управления локальным состоянием в приложении, которое я создаю, и у меня есть модальный компонент, который появляется при изменении состояния modalData. Чтобы он это услышал, он завернут в компонент <Query>, например:
render(){
return (
<Query query = {GET_MODAL_DATA}>
{({data}) => {
const currentModal = data.currentModal;
return (
<CSSTransition in = {currentModal.operation ? true : false} unmountOnExit classNames = "modal" timeout = {{ enter: 1, exit: 200 }}>
<div className = "modal-container" onClick = {this.closeModal}>
<div onClick = {e => e.stopPropagation()}>
<h2>
{ currentModal.operation+' '+currentModal.dataType }
</h2>
</div>
</div>
</CSSTransition>
)
}}
</Query>
)
}
однако при таком расположении он выполняет повторный рендеринг (и повторные запросы) независимо от того, что вы делаете.
Изменить маршрут? Повторные рендеры. Изменить локальное состояние другого компонента? Повторные рендеры. Изменить текстовые поля? Повторные рендеры.
Возможно, именно так и должен работать Apollo, но, исходя из Redux, кажется неэффективным для каждого установленного компонента повторно запрашивать, если вы хотя бы дышите в направлении своего браузера.
Это то, что он должен делать, или я что-то неправильно настроил?





response-apollo будет повторно запрашивать каждый раз, если вы не установите fetchPolicy на network-only.
Что касается повторного рендеринга, это скорее проблема React, чем Apollo.
Видите ли, каждый раз, когда состояние или свойство изменяется, react запускает функцию компонента render(). Если React обнаружит, что реквизиты для компонента изменились, он повторно отрендерит компонент.
Поскольку вы используете встроенную функцию в качестве дочерней опоры для компонента Query, это будет вызывать повторную визуализацию каждый раз, потому что каждый экземпляр функции является ссылкой на другой адрес памяти и, следовательно, воспринимается как другой. Что вы можете сделать с этим, так это вынести функцию в: скажем, в this.renderModal. Затем просто передайте функцию a children в Query следующим образом:
<Query>{this.renderModal}</Query>
Это гарантирует, что свойство children, передаваемое в Query, каждый раз будет одной и той же функцией.
Во-вторых, вы передаете литеральный объект { enter: 1, exit: 200 } компоненту CSSTransition. Это та же проблема, что и выше. Каждый экземпляр объекта также имеет ссылку на другой адрес памяти, даже если значение точно такое же. Единственное, что вы можете сделать с этим, - это вынуть объект и поместить его в constructor как
this.transitionTimeout = { enter: 1, exit: 200 };
а затем передайте эту переменную как опору, например:
<CSSTransition timeout = {this.transitionTimeout}
Это гарантирует, что опора будет указывать на один и тот же объект каждый раз, предотвращая повторную визуализацию.
Обновлять:
Вы также можете узнать о React.PureComponent. Вот статья, который довольно хорошо объясняет это. В основном response будет сравнивать значение предыдущего и следующего реквизита неглубоко, и если оно равно, он не будет запускать render.