@@ -11,10 +11,11 @@ type Props = { posts: Post[] | |||||
export default (({ posts, onClick }: Props) => ( | export default (({ posts, onClick }: Props) => ( | ||||
<div className="flex flex-wrap gap-6 p-4"> | <div className="flex flex-wrap gap-6 p-4"> | ||||
{posts.map ((post, i) => ( | {posts.map ((post, i) => ( | ||||
<PrefetchLink to={`/posts/${ post.id }`} | |||||
key={post.id} | |||||
className="w-40 h-40 overflow-hidden rounded-lg shadow-md hover:shadow-lg" | |||||
onClick={onClick}> | |||||
<PrefetchLink | |||||
to={`/posts/${ post.id }`} | |||||
key={post.id} | |||||
className="w-40 h-40 overflow-hidden rounded-lg shadow-md hover:shadow-lg" | |||||
onClick={onClick}> | |||||
<img src={post.thumbnail || post.thumbnailBase || undefined} | <img src={post.thumbnail || post.thumbnailBase || undefined} | ||||
alt={post.title || post.url} | alt={post.title || post.url} | ||||
title={post.title || post.url || undefined} | title={post.title || post.url || undefined} | ||||
@@ -16,13 +16,13 @@ type Props = AnchorHTMLAttributes<HTMLAnchorElement> & { | |||||
export default (({ to, | export default (({ to, | ||||
replace, | |||||
className, | |||||
onMouseEnter, | |||||
onTouchStart, | |||||
onClick, | |||||
cancelOnError = false, | |||||
...rest }: Props) => { | |||||
replace, | |||||
className, | |||||
onMouseEnter, | |||||
onTouchStart, | |||||
onClick, | |||||
cancelOnError = false, | |||||
...rest }: Props) => { | |||||
const navigate = useNavigate () | const navigate = useNavigate () | ||||
const qc = useQueryClient () | const qc = useQueryClient () | ||||
const url = useMemo (() => (new URL (to, location.origin)).toString (), [to]) | const url = useMemo (() => (new URL (to, location.origin)).toString (), [to]) | ||||
@@ -43,19 +43,19 @@ export default (({ user }: Props) => { | |||||
return next | return next | ||||
}, | }, | ||||
onMutate: async () => { | onMutate: async () => { | ||||
await qc.cancelQueries ({ queryKey: ['post', String (id)] }) | |||||
const prev = qc.getQueryData<any> (['post', String (id)]) | |||||
qc.setQueryData (['post', String (id)], | |||||
await qc.cancelQueries ({ queryKey: ['posts', String (id)] }) | |||||
const prev = qc.getQueryData<any> (['posts', String (id)]) | |||||
qc.setQueryData (['posts', String (id)], | |||||
(cur: any) => cur ? { ...cur, viewed: !(cur.viewed) } : cur) | (cur: any) => cur ? { ...cur, viewed: !(cur.viewed) } : cur) | ||||
return { prev } | return { prev } | ||||
}, | }, | ||||
onError: (...[, , ctx]) => { | onError: (...[, , ctx]) => { | ||||
if (ctx?.prev) | if (ctx?.prev) | ||||
qc.setQueryData (['post', String (id)], ctx.prev) | |||||
qc.setQueryData (['posts', String (id)], ctx.prev) | |||||
toast ({ title: '失敗……', description: '通信に失敗しました……' }) | toast ({ title: '失敗……', description: '通信に失敗しました……' }) | ||||
}, | }, | ||||
onSuccess: () => { | onSuccess: () => { | ||||
qc.invalidateQueries ({ queryKey: ['posts'] }) | |||||
qc.invalidateQueries ({ queryKey: ['posts', 'index'] }) | |||||
qc.invalidateQueries ({ queryKey: ['related', String (id)] }) | qc.invalidateQueries ({ queryKey: ['related', String (id)] }) | ||||
} }) | } }) | ||||