В настоящее время я использую React и Graphql с Apollo и react-apollo. Когда я хочу загрузить данные из Graphql, я обычно использую компонент <Query> из response-apollo, но если я хочу вызвать после события, такого как щелчок, насколько я знаю, мне нужно сделать это с помощью ApolloConsumer и client.query.
Но при этом, когда кеш обновляется или сбрасывается, все, что было загружено через ApolloConsumer, не обновляется. Вот пример:
import React, { Component } from "react";
import { render } from "react-dom";
import ApolloClient from "apollo-boost";
import { ApolloProvider, ApolloConsumer, Query } from "react-apollo";
import gql from "graphql-tag";
const client = new ApolloClient({
uri: `https://m08pj5j9k9.lp.gql.zone/graphql`
});
class App extends Component {
state = { client: [] };
renderQuery = () => {
return (
<Query query = {gql`{test01 {id, name}}`}>
{({ loading, error, data }) => {
if (loading) return "Loading...";
if (error) return "Error";
return (
<ul>
{data.test01.map(data => <li key = {data.id}>{data.name}</li>)}
</ul>
);
}}
</Query>
);
};
btnQueryClick = async client => {
const data = await client.query({ query: gql`{test02 {id, name}}` });
this.setState({ client: data.data.test02 });
};
render() {
return (
<ApolloProvider client = {client}>
<div>
<h2>Query test</h2>
{this.renderQuery()}
<ApolloConsumer>
{client => (
<div>
<h2>Client query test</h2>
<button onClick = {() => this.btnQueryClick(client)}>
Test!
</button>
<ul>
{this.state.client.map(data => (
<li key = {data.id}>{data.name}</li>
))}
</ul>
<h2>Store reset</h2>
<button
onClick = {() => {
client.resetStore();
}}
>
{" "}
Reset!
</button>
</div>
)}
</ApolloConsumer>
</div>
</ApolloProvider>
);
}
}
render(<App />, document.getElementById("root"));
А вот ссылка, чтобы попробовать вживую: https://codesandbox.io/s/5460952y3k
Во всех запросах я добавил случайное число, поэтому я знаю, изменились ли данные. Как видите, данные в разделе «Тест запроса» будут обновлены, если я нажму кнопку сброса, но не данные в разделе «Тест запроса клиента».
Есть ли способ имитировать такие же обновления с ApolloConsumer?
Спасибо
@TLadd, но даже если я не сохранил данные в состоянии, если я посмотрю на сетевые вкладки в браузере, я вижу, что test01 обновляется только после того, как я сбросил хранилище.





Да, я думаю, что для вашего конкретного случая использования client.query, вероятно, не подходит. Вот код, в котором, как мне кажется, вы ищете: https://codesandbox.io/s/yw779qx8qv
И источник:
import React, { Component } from "react";
import { render } from "react-dom";
import ApolloClient from "apollo-boost";
import { ApolloProvider, ApolloConsumer, Query } from "react-apollo";
import gql from "graphql-tag";
const client = new ApolloClient({
uri: `https://m08pj5j9k9.lp.gql.zone/graphql`
});
class App extends Component {
state = { showOtherQuery: false };
renderQuery = () => {
return (
<Query query = {gql`{test01 {id, name}}`}>
{({ loading, error, data }) => {
if (loading) return "Loading...";
if (error) return "Error";
return (
<ul>
{data.test01.map(data => <li key = {data.id}>{data.name}</li>)}
</ul>
);
}}
</Query>
);
};
renderOtherQuery() {
return (
<Query query = {gql`{test02 {id, name}}`}>
{({ loading, error, data }) => {
if (loading) return "Loading...";
if (error) return "Error";
return (
<ul>
{data.test02.map(data => <li key = {data.id}>{data.name}</li>)}
</ul>
);
}}
</Query>
);
}
render() {
return (
<ApolloProvider client = {client}>
<div>
<h2>Query test</h2>
{this.renderQuery()}
<div>
<h2>Client query test</h2>
<button onClick = {() => this.setState({ showOtherQuery: true })}>
Test!
</button>
{this.state.showOtherQuery && this.renderOtherQuery()}
<h2>Store reset</h2>
<button
onClick = {() => {
client.resetStore();
}}
>
{" "}
Reset!
</button>
</div>
</div>
</ApolloProvider>
);
}
}
render(<App />, document.getElementById("root"));
По сути, кнопка больше не выдает запрос вручную с помощью client.query, а вместо этого устанавливает логическое значение, которое отображает дополнительный компонент запроса, который затем будет обновляться, как вы ожидаете, при сбросе хранилища.
Альтернативой является ручной вызов client.query и повторная установка состояния (что в основном и делает компонент Query) при нажатии кнопки сброса.
Вы не можете ожидать автоматического обновления запросов, запускаемых вручную.
Даже повторно отображаемый (если это произошло, но это не так) потребитель не будет «обновлять» событие, а затем не запрашивать, не обновлять состояние (и представление).
Запрос не создает никаких наблюдаемых - вы, вероятно, хотите смешивать ручные запросы с подписками.
Почему вам нужно следить за другими обновлениями кеша?
Попробуйте использовать «традиционные» HOC Apollo и сочинить - IMHO намного более читабельным, управляемым и подходящим для более сложных сценариев.
Причина, по которой данные остаются, заключается в том, что вы сохраняете их в состоянии при вызове
this.setState({ client: data.data.test02 });. Когда вы сбрасываете хранилище, данных больше не будет в кеше, но они все равно будут в состоянии компонента. Вы можете обойти это, вручную сбросив состояние компонента, нажав кнопку сброса.