React Context - 删除用户帖子(在保留获取分页的路由之间同步删除)
React Context - Delete user posts (synchronize deletions between routes preserving fetching pagination)
简介
我正在尝试模拟典型的社交网络行为,其中 当用户删除他的一篇帖子时,它会在所有应用程序路由中自动删除。看看 Instagram 或 TikTok 背后的行为就知道了。
所以,我决定将所有用户的帖子放在一个上下文中:
export function UserPostsProvider({ children }) {
const [posts, dispatch] = useReducer(userPostsReducer, initialState);
const addUserPosts = (userId, posts, unshift = false) => {
dispatch(actionCreators.addUserPosts(userId, posts, unshift));
};
const deleteUserPost = (userId, postId) => {
dispatch(actionCreators.deleteUserPost(userId, postId));
};
const getUserPosts = (userId) => posts[userId] ?? [];
return (
<UserPostsContext.Provider
value={{
addUserPosts,
deleteUserPost,
getUserPosts,
}}
>
{children}
</UserPostsContext.Provider>
);
}
因此,当用户输入另一个用户个人资料时,帖子将添加到此上下文中。此外,当他向下滚动自己无穷无尽的帖子列表以删除他的旧出版物之一时,所有获取的帖子(从数据库中)也将添加到上下文中。
有了这个,我可以删除所有路由之间同步的帖子。但是... RAM 和性能如何?
问题
我用这个解决方案发现了一个优点和一个缺点:
PRO:
由于所有获取的帖子都位于上下文中,我们可以避免获取之前获取的内容,在某种内存缓存中转换上下文。
缺点:
卸载另一个用户配置文件的堆栈屏幕时,不会从上下文中删除帖子...随着时间的推移,RAM 将线性增加。
我该如何解决这个问题?有什么想法吗?
因为,如果在我的组件中,我只是这样做:
function UserPosts({ userData }) {
const postsContext = useContext(UserPostsContext);
const posts = postsContext.getUserPosts(userData.id);
const getMorePosts = () => {
... getting posts from DB with pagination
}
return <CardList data={posts} ... />
}
我根本无法实现数据分页(仅当帖子未存储在数据库中时),因为我从上下文中一次获取所有用户帖子,而 FlatList 将呈现所有其中,造成了很大的性能问题。
两条建议:
使用分页而不是在一个请求中加载所有 post。向上滚动 down/scroll,新请求将发送到服务器并获取数据尾部。例如,您可以获得每个请求偏移 10 post 或更多的旧 post。还可以使用 CDN 现金和适当的现金政策,您可以管理像 Instagram 这样的专业应用程序。
您可以在 useEffect
清理函数中定义一个方法(操作)来清除页面卸载时的上下文值:
例如:
useEffect(() => {
return () => // here call the cleaner function
}, [])
如您问题的评论中所述。
我的建议是将套接字用于类似这样的事情,而不是将所有内容都存储在上下文中。相反,上下文应该只用于真正全局的事物,而对于 comments/likes 等其他事物,您应该使用套接字来更新 incoming/outgoing 消息。例如构建一个小的“评论”或“消息”组件并让他们每个人订阅自己的套接字。
更重要的是,如果您正在使用“喜欢”或“评论”之类的东西,那么让它实时更新的唯一方法是使用套接字或通过不断的请求向您的后端发送垃圾邮件。
为此,您需要向 API 添加套接字,因此在“comment/9283012/like”之类的路由中,您可以发布一个“类似”事件(或其他)其他用户或特定用户可以收听,这将在 return 中更新您创建的特定“评论”或“消息”组件。
简介
我正在尝试模拟典型的社交网络行为,其中 当用户删除他的一篇帖子时,它会在所有应用程序路由中自动删除。看看 Instagram 或 TikTok 背后的行为就知道了。
所以,我决定将所有用户的帖子放在一个上下文中:
export function UserPostsProvider({ children }) {
const [posts, dispatch] = useReducer(userPostsReducer, initialState);
const addUserPosts = (userId, posts, unshift = false) => {
dispatch(actionCreators.addUserPosts(userId, posts, unshift));
};
const deleteUserPost = (userId, postId) => {
dispatch(actionCreators.deleteUserPost(userId, postId));
};
const getUserPosts = (userId) => posts[userId] ?? [];
return (
<UserPostsContext.Provider
value={{
addUserPosts,
deleteUserPost,
getUserPosts,
}}
>
{children}
</UserPostsContext.Provider>
);
}
因此,当用户输入另一个用户个人资料时,帖子将添加到此上下文中。此外,当他向下滚动自己无穷无尽的帖子列表以删除他的旧出版物之一时,所有获取的帖子(从数据库中)也将添加到上下文中。
有了这个,我可以删除所有路由之间同步的帖子。但是... RAM 和性能如何?
问题
我用这个解决方案发现了一个优点和一个缺点:
PRO:
由于所有获取的帖子都位于上下文中,我们可以避免获取之前获取的内容,在某种内存缓存中转换上下文。
缺点:
卸载另一个用户配置文件的堆栈屏幕时,不会从上下文中删除帖子...随着时间的推移,RAM 将线性增加。
我该如何解决这个问题?有什么想法吗?
因为,如果在我的组件中,我只是这样做:
function UserPosts({ userData }) {
const postsContext = useContext(UserPostsContext);
const posts = postsContext.getUserPosts(userData.id);
const getMorePosts = () => {
... getting posts from DB with pagination
}
return <CardList data={posts} ... />
}
我根本无法实现数据分页(仅当帖子未存储在数据库中时),因为我从上下文中一次获取所有用户帖子,而 FlatList 将呈现所有其中,造成了很大的性能问题。
两条建议:
使用分页而不是在一个请求中加载所有 post。向上滚动 down/scroll,新请求将发送到服务器并获取数据尾部。例如,您可以获得每个请求偏移 10 post 或更多的旧 post。还可以使用 CDN 现金和适当的现金政策,您可以管理像 Instagram 这样的专业应用程序。
您可以在
useEffect
清理函数中定义一个方法(操作)来清除页面卸载时的上下文值:
例如:
useEffect(() => {
return () => // here call the cleaner function
}, [])
如您问题的评论中所述。
我的建议是将套接字用于类似这样的事情,而不是将所有内容都存储在上下文中。相反,上下文应该只用于真正全局的事物,而对于 comments/likes 等其他事物,您应该使用套接字来更新 incoming/outgoing 消息。例如构建一个小的“评论”或“消息”组件并让他们每个人订阅自己的套接字。
更重要的是,如果您正在使用“喜欢”或“评论”之类的东西,那么让它实时更新的唯一方法是使用套接字或通过不断的请求向您的后端发送垃圾邮件。
为此,您需要向 API 添加套接字,因此在“comment/9283012/like”之类的路由中,您可以发布一个“类似”事件(或其他)其他用户或特定用户可以收听,这将在 return 中更新您创建的特定“评论”或“消息”组件。