我正在构建一个 React 应用程序,它基本上是一个照片共享应用程序。
以下是一些用例:
- 用户可以上传照片和视频
- 用户可以在列表视图中查看照片
- 用户可以对列表中的照片重新排序
- 用户可以从列表中选择照片并根据他们的选择执行操作
- 用户可以为这些照片赋予属性,例如消息、标题等。 让我们将图像 + 其属性称为帖子
以下是一些主要的体系结构组件:
- 用于上传、托管和转换图像和视频创建的 CDN 服务
- 与数据库配对的后端应用程序用于持久存储
我正在寻找一种在状态中组织所有这些数据的好方法。我的一个想法是将状态分解为单独的简单数据结构。
大致如下:
posts <Array> maps Post index to Post ID
media <Object> maps Post ID to Image Urls
selectedPosts <Object> maps Post ID to Boolean
loadingPosts <Object> maps Post ID to Boolean
所以这里我们有四种数据结构。
帖子- :确定哪些帖子处于状态以及按什么顺序
- 媒体:将帖子 ID 归因于图片网址
- 所选帖子:确定选择哪些帖子 加载
- 帖子:确定给定帖子是否正在加载
我通过四个 React 上下文呈现这些内容
将状态分解为单独的上下文使依赖组件能够非常轻松地订阅它们所需的状态。例如:
import React from 'react'
import useMedia from '/hooks/media'
export default ({ postId }) => {
const { media } = useMedia() // useMedia uses useContext under the hood
const imageForThisPost = media[postId]
return (
<Image src={imageForThisPost}/>
)
}
我真正喜欢的是,这个组件从全局状态中获取它需要的状态,并且实际上只有一个重新渲染的理由(假装我正在使用useMemo或其他东西(。我过去曾使用过一些艰难的 React Redux Web 应用程序,其中每个组件在任何状态更改时都会重新渲染,因为所有状态都在一个数据结构中(尽管记忆选择器可以解决这个问题(。
当涉及到影响多个上下文的用例时,就会出现问题。以上传图片为例:
上传照片的事件顺序如下所示:
- ID 为"ABC"的空帖子被选中。更新所选帖子上下文
- 用户上传文件,我们等待 CDN 返回图像网址
- 更新 ABC 后加载上下文(加载 == true( (接收图像网址(
- 在ABC更新帖子上下文
- 更新 ABC 的媒体上下文
- 更新 ABC 帖子的加载上下文(加载 == 假(
- 取消选择发布 ABC。更新所选帖子上下文
像这样的长而复杂的异步序列很难处理、封装、重用和测试。
对于像这样具有可能很长的异步操作序列和有点复杂的状态的中型 Web 应用程序,有什么更好的方法来组织状态?
愿望清单:
- 易于控制重新渲染
- 易于添加扩展/更改应用程序功能(不喜欢庞大的深度嵌套数据结构(
- 易于测试
- 不使用 Redux(但使用Reducer很好((我只是不喜欢 redux 带来的巨大开销(
有人有什么想法吗?
我知道一种方法可能是使用 useReducer、动作和选择器来模拟 Redux。值得庆幸的是dispatch
React 中是一个稳定的函数身份。Idk,我真的不喜欢处理大而深嵌套的对象。当产品需求发生变化时,处理起来非常痛苦,因为整个应用程序都依赖于特定的架构形状。
旧帖子,但我假设 selectedPosts 和 loadPosts 是过滤的帖子对象。
就个人而言,我可能不会将它们分开,而是过滤标记为加载/选择的帖子并通过某些操作在代码中上传这些帖子?
即状态有帖子列表,加载/选定的道具和代码会过滤要上传的帖子 - 您是否过于复杂了?假设一些查找一对多/多对多?在国家媒体创建协会?你最后做了什么?我将使用 useReducer 并调度更新到状态,除非它深度嵌套,否则不确定是否需要上下文。