В настоящее время я создаю простой рабочий процесс CRUD с использованием React и GraphQL. После создания объекта (в данном случае article, который состоит только из id, title и description.), я возвращаюсь на страницу Index, на которой отображаются все созданные в данный момент статьи. Моя проблема заключается в том, что после создания статьи на индексной странице созданная статья не отображается, пока я не обновлю страницу. Я использую apollo для запроса API-интерфейса graphql и отключил кеширование, поэтому я не уверен, почему данные не отображаются. Я установил точки останова в моей функции ArticlesIndex's componentDidMount и убедился, что она выполняется, и во время выполнения база данных действительно включает недавно добавленную article.
Моя серверная сторона на самом деле никогда не срабатывает, когда выполняется запрос на стороне клиента для получения всех статей. Я не уверен, что кэширует эти данные и почему они не извлекаются с сервера, как ожидалось.
Мой компонент ArticlesCreate вставляет новую запись и перенаправляет обратно на компонент ArticlesIndex следующим образом:
handleSubmit(event) {
event.preventDefault();
const { client } = this.props;
var article = {
"article": {
"title": this.state.title,
"description": this.state.description
}
};
client
.mutate({ mutation: CREATE_EDIT_ARTICLE,
variables: article })
.then(({ data: { articles } }) => {
this.props.history.push("/articles");
})
.catch(err => {
console.info("err", err);
});
}
}
тогда мой компонент ArticlesIndex извлекает все статьи из базы данных следующим образом:
componentDidMount = () => {
const { client } = this.props; //client is an ApolloClient
client
.query({ query: GET_ARTICLES })
.then(({ data: { articles } }) => {
if (articles) {
this.setState({ loading: false, articles: articles });
}
})
.catch(err => {
console.info("err", err);
});
};
и я настроил ApolloClient, чтобы он не кэшировал данные, как в моем App.js, следующим образом:
const defaultApolloOptions = {
watchQuery: {
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
}
export default class App extends Component {
displayName = App.name;
client = new ApolloClient({
uri: "https://localhost:44360/graphql",
cache: new InMemoryCache(),
defaultOptions: defaultApolloOptions
});
//...render method, route definitions, etc
}
Почему это происходит и как я могу это решить?
articles действительно является массивом, однако настройка состояния работает правильно. Проблема, насколько я понял, заключается в том, что articles в обратном вызове .then моего запроса в componentDidMount содержит устаревшие данные (до того, как был выполнен вызов создания)
Как ты возвращаешься? Кнопка «Назад» в браузере или вызов компонента «Индекс»?
this.props.history.push("/articles"); в компоненте ArticlesCreate (этот маршрут предназначен для компонента ArticlesIndex




Я вижу, что вы получаете данные и устанавливаете состояние своих компонентов при начальном монтировании. Скорее всего, когда вы перенаправляете, он не запускает хук жизненного цикла componentDidMount, поскольку он уже смонтирован, если это проблема, попробуйте использовать хук жизненного цикла компонентдидобдате, чтобы ваш компонент знал, что было обновление, и повторно установил данные.
Он устанавливает состояние, поэтому следует вызывать рендеринг. Вы должны звонить серверу из componentDidMount, а не из componentDidUpdate
Я могу подтвердить, что componentDidMount вызывается после того, как мой компонент создания перенаправляется обратно к моему индексному компоненту. Однако по какой-то причине запрос, похоже, на самом деле не выполняется и работает с устаревшими данными. (articles в обратном вызове не обновляется, но этот код выполняется)
Похоже, проблема в том, что ApolloBoost не поддерживает defaultOptions, как было отмечено в этом выпуске github. Чтобы решить проблему, я изменил:
const defaultApolloOptions = {
watchQuery: {
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
}
export default class App extends Component {
displayName = App.name;
client = new ApolloClient({
uri: "https://localhost:44360/graphql",
cache: new InMemoryCache(),
defaultOptions: defaultApolloOptions
});
//...render method, route definitions, etc
}
К:
const client = new ApolloClient({
uri: "https://localhost:44360/graphql"
});
client.defaultOptions = {
watchQuery: {
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
};
export default class App extends Component {
//....
}
Предполагая, что
articlesявляется массивомthis.setState({ loading: false, articles: [...articles] });? Или JSON нужно парсить?