React 简单全局实体缓存而不是 Flux/React/etc
React Simple Global Entity Cache instead of Flux/React/etc
我正在写一个小 "fun" Scala/Scala.js 项目。
在我的服务器上,我有被 uuid
-s 引用的实体
(在 Ref-s 内)。
为了"fun",我不想使用flux/redux架构,但仍然在客户端使用React(使用ScalaJS-React)。
我想做的是有一个简单的缓存,例如:
- 当 React
UserDisplayComponent
想要显示 Entity
User
和 uuid=0003
- 然后
render()
方法调用 Cache
(作为 prop
传入)
- 假设这是
UserDisplayComponent
第一次要求这个特定的 User
(uuid=0003
),而 Cache
还没有
- 然后
Cache
生成 AjaxCall
从服务器 获取 User
- 当
AjaxCall
return 时 Cache
触发 re-render
- 但是!现在,当组件从
Cache
请求 User
时,它会立即从 Cache
获取 User
Entity
并且不会触发 AjaxCall
我想实现的方式如下:
- 我开始
render()
- "stuff" inside
render()
向 Cache
询问各种 Entities
Cache
returns Loading
或 Entity
本身。
- 在渲染结束时,
Cache
将所有 AjaxRequest
-s 发送到服务器并等待所有 return
- 一旦所有
AjaxRequests
都已 returned(让我们假设他们这样做 - 为了简单起见)Cache
触发“re-render()
”,现在所有Cache
立即提供之前请求的实体。
- 当然,新到达的
Entity
-s 可能会触发 render()
获取更多 Entity
-s,例如,如果我加载一个 Entity
例如 case class UserList(ul: List[Ref[User]])
类型。不过我们现在不用担心这个了。
问题:
1) 如果我以这种方式处理状态,我真的做错了什么吗?
2) 是否有现成的解决方案?
我环顾四周,但一切都是 FLUX/REDUX 等等......沿着这些线...... - 我想避免为了:
- "fun"
- 好奇心
- 探索
- 玩耍
- 我认为这个简单的缓存对于我的用例来说会更简单,因为我想以一种简单的方式将基于 "REF" 的 "domain model" 带到客户端:就好像客户端是服务器和网络将无限快且零延迟(这是缓存将模拟的)。
考虑构建丰富的动态 Web 需要解决哪些问题 UI,以及哪些库/层通常会为您处理这些问题。
1. DOM事件(点击等)需要触发State的变化
这个比较容易。 DOM 节点公开基于回调的侦听器 API 可以直接适应任何架构。
2。 State 的变化需要触发 DOM 个节点的更新
这比较棘手,因为它需要高效并以可维护的方式完成。您不想在状态发生变化时从头开始重新渲染整个组件,也不想编写大量 jquery 风格的意大利面条代码来手动更新 DOM即使在运行时高效,也太容易出错。
这个问题主要是为什么像 React 这样的库存在的原因,它们将其抽象到虚拟 DOM 之后。但是你也可以在没有虚拟 DOM 的情况下将其抽象出来,就像我自己的 Laminar 库所做的那样。
放弃库解决这个问题只适用于更简单的应用程序。
3。组件应该能够读/写 Global State
这是flux/redux解决的部分。具体来说,这些都是问题 #1 和 #2,除了应用于全局状态而不是组件状态。
4。缓存
缓存很难,因为缓存需要在某个时候无效,在上面的所有其他内容之上。
Flux / redux 对此毫无帮助。提供帮助的库之一是 Relay,它的工作方式与您提出的解决方案非常相似,只是方式更精细,并且位于 React 和 GraphQL 之上。阅读其文档将帮助您解决问题。如果您不需要整个 React / GraphQL 包袱,您绝对可以用普通的 Scala.js 实现中继功能的一小部分,但您需要了解现有技术。
5.序列化和类型安全
这是此列表中 唯一 问题,与 Scala.js 相关,而不是 Javascript 和一般 SPA。
Scala 对象需要序列化才能在网络上传输。进入 JSON、protobufs 或其他任何东西,但您需要一个不会涉及容易出错的手动工作的系统。有许多 Scala.js 库解决了这个问题,例如 upickle、Autowire、endpoints、sloth 等。关键字:"Scala JSON library",或“Scala type-safe RPC",取决于你想要什么样的解决方案。
我希望这些原则足以作为答案。当您了解这些问题时,您的解决方案是否适用于给定的用例就很明显了。事实上,您没有描述您的解决方案如何解决问题 2、4 和 5。您可以使用我提到的一些库或使用类似的想法/算法实现您自己的解决方案。
关于一个小的技术说明,考虑为您的缓存层实现一个异步的、基于未来的 API,以便它 returns Future[Entity]
而不是 Loading | Entity
。
我正在写一个小 "fun" Scala/Scala.js 项目。
在我的服务器上,我有被 uuid
-s 引用的实体
(在 Ref-s 内)。
为了"fun",我不想使用flux/redux架构,但仍然在客户端使用React(使用ScalaJS-React)。
我想做的是有一个简单的缓存,例如:
- 当 React
UserDisplayComponent
想要显示Entity
User
和uuid=0003
- 然后
render()
方法调用Cache
(作为prop
传入) - 假设这是
UserDisplayComponent
第一次要求这个特定的User
(uuid=0003
),而Cache
还没有 - 然后
Cache
生成AjaxCall
从服务器 获取 - 当
AjaxCall
return 时Cache
触发re-render
- 但是!现在,当组件从
Cache
请求User
时,它会立即从Cache
获取User
Entity
并且不会触发AjaxCall
User
我想实现的方式如下:
- 我开始
render()
- "stuff" inside
render()
向Cache
询问各种Entities
Cache
returnsLoading
或Entity
本身。- 在渲染结束时,
Cache
将所有AjaxRequest
-s 发送到服务器并等待所有 return - 一旦所有
AjaxRequests
都已 returned(让我们假设他们这样做 - 为了简单起见)Cache
触发“re-render()
”,现在所有Cache
立即提供之前请求的实体。 - 当然,新到达的
Entity
-s 可能会触发render()
获取更多Entity
-s,例如,如果我加载一个Entity
例如case class UserList(ul: List[Ref[User]])
类型。不过我们现在不用担心这个了。
问题:
1) 如果我以这种方式处理状态,我真的做错了什么吗?
2) 是否有现成的解决方案?
我环顾四周,但一切都是 FLUX/REDUX 等等......沿着这些线...... - 我想避免为了:
- "fun"
- 好奇心
- 探索
- 玩耍
- 我认为这个简单的缓存对于我的用例来说会更简单,因为我想以一种简单的方式将基于 "REF" 的 "domain model" 带到客户端:就好像客户端是服务器和网络将无限快且零延迟(这是缓存将模拟的)。
考虑构建丰富的动态 Web 需要解决哪些问题 UI,以及哪些库/层通常会为您处理这些问题。
1. DOM事件(点击等)需要触发State的变化
这个比较容易。 DOM 节点公开基于回调的侦听器 API 可以直接适应任何架构。
2。 State 的变化需要触发 DOM 个节点的更新
这比较棘手,因为它需要高效并以可维护的方式完成。您不想在状态发生变化时从头开始重新渲染整个组件,也不想编写大量 jquery 风格的意大利面条代码来手动更新 DOM即使在运行时高效,也太容易出错。
这个问题主要是为什么像 React 这样的库存在的原因,它们将其抽象到虚拟 DOM 之后。但是你也可以在没有虚拟 DOM 的情况下将其抽象出来,就像我自己的 Laminar 库所做的那样。
放弃库解决这个问题只适用于更简单的应用程序。
3。组件应该能够读/写 Global State
这是flux/redux解决的部分。具体来说,这些都是问题 #1 和 #2,除了应用于全局状态而不是组件状态。
4。缓存
缓存很难,因为缓存需要在某个时候无效,在上面的所有其他内容之上。
Flux / redux 对此毫无帮助。提供帮助的库之一是 Relay,它的工作方式与您提出的解决方案非常相似,只是方式更精细,并且位于 React 和 GraphQL 之上。阅读其文档将帮助您解决问题。如果您不需要整个 React / GraphQL 包袱,您绝对可以用普通的 Scala.js 实现中继功能的一小部分,但您需要了解现有技术。
5.序列化和类型安全
这是此列表中 唯一 问题,与 Scala.js 相关,而不是 Javascript 和一般 SPA。
Scala 对象需要序列化才能在网络上传输。进入 JSON、protobufs 或其他任何东西,但您需要一个不会涉及容易出错的手动工作的系统。有许多 Scala.js 库解决了这个问题,例如 upickle、Autowire、endpoints、sloth 等。关键字:"Scala JSON library",或“Scala type-safe RPC",取决于你想要什么样的解决方案。
我希望这些原则足以作为答案。当您了解这些问题时,您的解决方案是否适用于给定的用例就很明显了。事实上,您没有描述您的解决方案如何解决问题 2、4 和 5。您可以使用我提到的一些库或使用类似的想法/算法实现您自己的解决方案。
关于一个小的技术说明,考虑为您的缓存层实现一个异步的、基于未来的 API,以便它 returns Future[Entity]
而不是 Loading | Entity
。