Need advice on caching data retrieved from useeffect in react

hey guys so im currently working on a project that will retrieve reddit posts and filter them by pain points similar to GummySearch but for a single niche to generate potential business ideas! the reason im building this is cuz i cant pay $60 for gummy search 😦 and i thought it would be cool to build my own version to use for free for a single niche anyways the problem is with the call to Reddit API now with useeffects in general the its called whenever the component mounts right but i dont want to do that. whats the best way to cache the posts retrieved from Reddits API on the client? i want to be refetching only after every 2 hours ! so say the user opens the app it fetches posts and then if the component unmounts and remounts i want to check if its been 2 hours since the last time, how can i do that check?? also where do i store the fetched posts? on local storage? do i save them to the database? im currently not saving them to the database so im not sure whats the best method? if its not been 2 hours then i could fetch from the database ? if thats the case how would i model my relationships ? as i dont have a POST model yet in my Prisma PostgreSQL database ill share my code for all relevant files
1 Reply
chikanlegbees
chikanlegbeesOP•7d ago
// prisma schema
model User {
id String @id @default(uuid())
email String @unique
username String @unique
password String?
createdAt DateTime @default(now())
refreshToken String?
googleId String? @unique
photo String?
audiences Audience[]

@@map("users")
}

model Audience {
id String @id @default(uuid())
title String
searchTerm String @default("")
createdAt DateTime @default(now())
userId String
user User @relation(fields: [userId], references: [id])
subreddits Subreddit[]

@@map("audiences")
}

model Subreddit {
id String @id @default(uuid())
name String @unique
title String
subscribers Int
icon String
url String
audiences Audience[]

@@map("subreddits")
}
// prisma schema
model User {
id String @id @default(uuid())
email String @unique
username String @unique
password String?
createdAt DateTime @default(now())
refreshToken String?
googleId String? @unique
photo String?
audiences Audience[]

@@map("users")
}

model Audience {
id String @id @default(uuid())
title String
searchTerm String @default("")
createdAt DateTime @default(now())
userId String
user User @relation(fields: [userId], references: [id])
subreddits Subreddit[]

@@map("audiences")
}

model Subreddit {
id String @id @default(uuid())
name String @unique
title String
subscribers Int
icon String
url String
audiences Audience[]

@@map("subreddits")
}
const fetchPosts = async (
sort = "hot",
controller,
setAllPosts,
subreddits,
setLoading,
) => {
try {
setLoading(true);
const response = await fetch(
`${import.meta.env.VITE_SERVER_URL}/api/reddit/reddit-posts`,
{
mode: "cors",
method: "POST",
credentials: "include",
signal: controller.signal,
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ sort, subreddits }),
},
);
if (!response.ok) {
console.log("response failed");
return;
}
const data = await response.json();
setAllPosts(data);
setLoading(false);
} catch (err) {
console.log("Failed in fetch posts", err);
}
};

export default fetchPosts;

useEffect(() => {
const controller = new AbortController();
fetchPosts(
"hot",
controller,
setAllPosts,
singleAudience.subreddits,
setLoading,
);
return () => {
controller.abort();
};
}, [setAllPosts, singleAudience.subreddits]);
const fetchPosts = async (
sort = "hot",
controller,
setAllPosts,
subreddits,
setLoading,
) => {
try {
setLoading(true);
const response = await fetch(
`${import.meta.env.VITE_SERVER_URL}/api/reddit/reddit-posts`,
{
mode: "cors",
method: "POST",
credentials: "include",
signal: controller.signal,
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ sort, subreddits }),
},
);
if (!response.ok) {
console.log("response failed");
return;
}
const data = await response.json();
setAllPosts(data);
setLoading(false);
} catch (err) {
console.log("Failed in fetch posts", err);
}
};

export default fetchPosts;

useEffect(() => {
const controller = new AbortController();
fetchPosts(
"hot",
controller,
setAllPosts,
singleAudience.subreddits,
setLoading,
);
return () => {
controller.abort();
};
}, [setAllPosts, singleAudience.subreddits]);
// backend

const fetchPost = async (req, res) => {
const sort = req.body.sort || "hot";
const subs = req.body.subreddits;
const token = await getAccessToken();
const subredditPromises = subs.map(async (sub) => {
const redditRes = await fetch(
`https://oauth.reddit.com/r/${sub.name}/${sort}?limit=100`,
{
headers: {
Authorization: `Bearer ${token}`,
"User-Agent": userAgent,
},
},
);

const data = await redditRes.json();
if (!redditRes.ok) {
return [];
}

const filteredPosts =
data?.data?.children
?.filter((post) => {
const { author, distinguished } = post.data;
return author !== "AutoModerator" && distinguished !== "moderator";
})
.map((post) => ({
title: post.data.title,
url: `https://reddit.com${post.data.permalink}`,
subreddit: sub,
upvotes: post.data.ups,
comments: post.data.num_comments,
author: post.data.author,
flair: post.data.link_flair_text,
selftext: post.data.selftext,
})) || [];

return await classifyPainPoints(filteredPosts);
});

const allPostsArrays = await Promise.all(subredditPromises);
const allPosts = allPostsArrays.flat();

return res.json(allPosts);
};
// backend

const fetchPost = async (req, res) => {
const sort = req.body.sort || "hot";
const subs = req.body.subreddits;
const token = await getAccessToken();
const subredditPromises = subs.map(async (sub) => {
const redditRes = await fetch(
`https://oauth.reddit.com/r/${sub.name}/${sort}?limit=100`,
{
headers: {
Authorization: `Bearer ${token}`,
"User-Agent": userAgent,
},
},
);

const data = await redditRes.json();
if (!redditRes.ok) {
return [];
}

const filteredPosts =
data?.data?.children
?.filter((post) => {
const { author, distinguished } = post.data;
return author !== "AutoModerator" && distinguished !== "moderator";
})
.map((post) => ({
title: post.data.title,
url: `https://reddit.com${post.data.permalink}`,
subreddit: sub,
upvotes: post.data.ups,
comments: post.data.num_comments,
author: post.data.author,
flair: post.data.link_flair_text,
selftext: post.data.selftext,
})) || [];

return await classifyPainPoints(filteredPosts);
});

const allPostsArrays = await Promise.all(subredditPromises);
const allPosts = allPostsArrays.flat();

return res.json(allPosts);
};
as u can see im not saving them to the database nor do i have a model for it would appreciate some advice

Did you find this page helpful?