Skip to content

Instantly share code, notes, and snippets.

@yuvalbl
Last active November 21, 2020 19:55
Show Gist options
  • Save yuvalbl/d963bfbd69a05e214027fbca36d6fb0a to your computer and use it in GitHub Desktop.
Save yuvalbl/d963bfbd69a05e214027fbca36d6fb0a to your computer and use it in GitHub Desktop.
Apollo ClientV3 power ups
import { gql, useQuery } from '@apollo/client';
const GET_DOGS = gql`
query GetDogs {
dogs {
id
breed
}
}
`;
function Dogs({ onDogSelected }) {
const { loading, error, data } = useQuery(GET_DOGS);
if (loading) return 'Loading...';
if (error) return `Error! ${error.message}`;
return (
<select name="dog" onChange={onDogSelected}>
{data.dogs.map(dog => (
<option key={dog.id} value={dog.breed}>
{dog.breed}
</option>
))}
</select>
);
}
// inner component
export function GraphQLRequest({ requestFunction, params, handleData }) {
if (typeof requestFunction !== 'function') {
return <ErrorAlert message={'Request function is not a function'} />
}
const { loading, error, data } = requestFunction(...params)
if (loading) {
return <div>Loading...</div>
}
if (error) {
return <ErrorAlert message={error.message} />
}
handleData(data)
return <div></div>
}
// outer component
export function SomeView({ match: { params } }) {
const [data, setData] = useState(null)
const id = params.someId
return (<div>
<p className='title'>SomeItem {id}</p>
<GraphQLRequest
handleData={data => setData(data)}
requestFunction={getSomeInfoFromId}
params={[id]}
/>
</div>)
}
const withUser = (WrappedComponent) => {
const user = sessionStorage.getItem('user');
return (props) => <WrappedComponent user={user} {...props} />;
};
const Avatar = ({ user }) => {...}
export default withUser(Avatar);
export const withQuery = (WrappedComponent, query) => {
// this won't work, since outer function is not a component
const { loading, error, data } = useQuery(query);
return (props) => {
return (<WrappedComponent data={data} {...props} />)
};
}
export const withQuery = (WrappedComponent, query) => {
return (props) => {
// the inner function is a component, so we're good :)
const { loading, error, data } = useQuery(query);
return (<WrappedComponent data={data} {...props} />)
};
}
export const withQuery = (WrappedComponent, query) => {
return (props) => {
const { loading, error, data, subscribeToMore } = useQuery(query);
if (loading) {
return <div>Loading</div>;
} else if (error) {
return <div>Error</div>;
}
return (<WrappedComponent data={data} more={subscribeToMore} {...props} />)
};
}
const MORE_DOGS = gql`
subscription MoreDogs {
dogAdded {
id
breed
}
}
`;
function Dogs({ data, more, onDogSelected }) {
useEffect(() => {
// subscribe to updates
more({
document: MORE_DOGS,
updateQuery: (prev, { subscriptionData }) => {
// your apollo cache logic here
},
});
}, [data, more]);
return (
<select name="dog" onChange={onDogSelected}>
{data.dogs.map(dog => (
<option key={dog.id} value={dog.breed}>
{dog.breed}
</option>
))}
</select>
);
}
export default withQuery(Dogs, GET_DOGS);
export const withQuery = (WrappedComponent, query) => {
return (props) => {
const { loading, error, data } = useQuery(query);
if (loading) {
return <div>Loading</div>;
} else if (error) {
return <div>Error</div>;
}
return (<WrappedComponent data={data} {...props} />)
};
}
const GET_DOGS = gql`
query GetDogs {
dogs {
id
breed
}
}
`;
function Dogs({ data, onDogSelected }) {
return (
<select name="dog" onChange={onDogSelected}>
{data.dogs.map(dog => (
<option key={dog.id} value={dog.breed}>
{dog.breed}
</option>
))}
</select>
);
}
export default withQuery(Dogs, GET_DOGS);
export const withQueries = (WrappedComponent, queries) => {
return (props) => {
const queryHooks = queries.map((query) => useQuery(query));
// calculate error and loading
const error = queryHooks.some((query) => query.error);
const loading = !error && queryHooks.some((query) => query.loading);
let data;
const allQueriesCompleted = queryHooks.every((result) => !!result.data);
if (allQueriesCompleted) {
// return data only if all queries completed
data = queryHooks
.map((result) => result.data)
.reduce((data1, data2) => ({
...data1,
...data2,
}));
}
if (loading) {
return <div>Loading</div>;
} else if (error) {
return <div>Error</div>;
}
return <WrappedComponent data={data} {...props} />;
};
};
function Dogs({ data }) {
// use data.dogs and data.somethingElse
}
export default withQueries(Dogs, [GET_DOGS, GET_SOMETHING_ELSE]);
export const withQueries = (WrappedComponent, queries) => {
return (props) => {
const queryHooks = queries.map((query) => useQuery(query));
// calculate error and loading
const error = queryHooks.some((query) => query.error);
const loading = !error && queryHooks.some((query) => query.loading);
let data;
let more;
const allQueriesCompleted = queryHooks.every((result) => !!result.data);
if (allQueriesCompleted) {
// return data only if all queries completed
data = queryHooks
.map((result) => result.data)
.reduce((data1, data2) => ({
...data1,
...data2,
}));
// return "more" function for each query
more = queryHooks.map((query) => query.subscribeToMore);
}
if (loading) {
return <div>Loading</div>;
} else if (error) {
return <div>Error</div>;
}
return <WrappedComponent data={data} more={more} {...props} />;
};
};
function CommentsPageWithData({ params }) {
const { subscribeToMore, ...result } = useQuery(
COMMENT_QUERY,
{ variables: { postID: params.postID } }
);
return (
<CommentsPage
{...result}
subscribeToNewComments={() =>
subscribeToMore({
document: COMMENTS_SUBSCRIPTION,
variables: { postID: params.postID },
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev;
const newFeedItem = subscriptionData.data.commentAdded;
return Object.assign({}, prev, {
post: {
comments: [newFeedItem, ...prev.post.comments]
}
});
}
})
}
/>
);
}
const MORE_DOGS = gql`
subscription MoreDogs {
dogAdded {
id
breed
}
}
`;
function Dogs({ data }) {
useEffect(() => {
// get "more" function for the first query
const subscriptionToMoreEvents = data.more[0];
// subscribe to updates
subscriptionToMoreEvents({
document: MORE_DOGS,
updateQuery: (prev, { subscriptionData }) => {
// your apollo cache logic here
},
});
}, [data]);
}
export default withQueries(Dogs, [GET_DOGS, GET_SOMETHING_ELSE]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment