Files
Zafor Abdullah 93c59f02f8 fix: error handling and loading states in with-apollo-and-redux example (#91457)
## For Contributors

### Fixing a bug

- Fixes #(open or reference an issue if one exists, otherwise omit)
- No tests required — this is an `examples/` change only
- No custom error links needed — failures are surfaced via Apollo's
built-in error state

---

## Summary

- `PostList` destructured `data` before checking `loading`/`error`, so
the component threw when `data` was `undefined` (e.g., on the initial
fetch or after a query error) instead of showing the loading/error UI.
- Move the `error`/`loading`/`!data` guard clauses above the `data`
destructuring and `loadMorePosts` definition, and add a `!data` check so
the component never accesses properties on an undefined value.
- Bump `graphql` (`14.5.8` → `16.13.1`) and `lodash` (`4.17.20` →
`4.17.23`) in the example's `package.json` to pick up fixes in
dependencies the example relies on.

## Note: 
Initially this PR suppose to target upstream DB issue
2026-07-21 17:44:56 +02:00

113 lines
2.7 KiB
JavaScript

import { gql, useQuery, NetworkStatus } from "@apollo/client";
import ErrorMessage from "./ErrorMessage";
import PostUpvoter from "./PostUpvoter";
export const ALL_POSTS_QUERY = gql`
query allPosts($first: Int!, $skip: Int!) {
allPosts(orderBy: { createdAt: desc }, first: $first, skip: $skip) {
id
title
votes
url
createdAt
}
_allPostsMeta {
count
}
}
`;
export const allPostsQueryVars = {
skip: 0,
first: 10,
};
export default function PostList() {
const { loading, error, data, fetchMore, networkStatus } = useQuery(
ALL_POSTS_QUERY,
{
variables: allPostsQueryVars,
// Setting this value to true will make the component rerender when
// the "networkStatus" changes, so we are able to know if it is fetching
// more data
notifyOnNetworkStatusChange: true,
},
);
const loadingMorePosts = networkStatus === NetworkStatus.fetchMore;
if (error) return <ErrorMessage message="Error loading posts." />;
if (loading && !loadingMorePosts) return <div>Loading</div>;
if (!data) return null;
const { allPosts, _allPostsMeta } = data;
const loadMorePosts = () => {
fetchMore({
variables: {
skip: allPosts.length,
},
});
};
const areMorePosts = allPosts.length < _allPostsMeta.count;
return (
<section>
<ul>
{allPosts.map((post, index) => (
<li key={post.id}>
<div>
<span>{index + 1}. </span>
<a href={post.url}>{post.title}</a>
<PostUpvoter id={post.id} votes={post.votes} />
</div>
</li>
))}
</ul>
{areMorePosts && (
<button onClick={() => loadMorePosts()} disabled={loadingMorePosts}>
{loadingMorePosts ? "Loading..." : "Show More"}
</button>
)}
<style jsx>{`
section {
padding-bottom: 20px;
}
li {
display: block;
margin-bottom: 10px;
}
div {
align-items: center;
display: flex;
}
a {
font-size: 14px;
margin-right: 10px;
text-decoration: none;
padding-bottom: 0;
border: 0;
}
span {
font-size: 14px;
margin-right: 5px;
}
ul {
margin: 0;
padding: 0;
}
button:before {
align-self: center;
border-style: solid;
border-width: 6px 4px 0 4px;
border-color: #ffffff transparent transparent transparent;
content: "";
height: 0;
margin-right: 5px;
width: 0;
}
`}</style>
</section>
);
}