如何在不复制片段的情况下传递道具
Posted
技术标签:
【中文标题】如何在不复制片段的情况下传递道具【英文标题】:How to pass down props without duplicating fragments 【发布时间】:2021-03-08 17:13:29 【问题描述】:我的父组件以嵌套片段结束,如下所示:
query MyAppQuery(
$id
$a
$b
$c
)
viewer
...App_viewer
...ComponentA_viewer @include(if: $a)
...ComponentB_viewer @include(if: $b)
...ComponentC_viewer @include(if: $c)
allEmployees: allUsers(userType: "1")
...ComponentA_allEmployees @include(if: $a)
...ComponentB_allEmployees @include(if: $b)
...ComponentC_allEmployees @include(if: $c)
;
如果我不包含所有这些子片段但所有这些子片段的数据相同,则中继失败,必须在我的所有需要登录用户的子组件上声明视图片段似乎很愚蠢。
我怎样才能在我的应用程序顶部请求这段数据并将其提供给子组件,而不必包含所有这些片段。
这开始感觉像是反向道具钻探,我必须在我的应用程序的下端声明一个片段并将其传递到链上。
与 allEmployees 相同。这是我应该只获取一次并通过上下文传递或访问的相同数据,但我必须传递所有这些愚蠢的片段或转发抱怨。
【问题讨论】:
【参考方案1】:这是 Relay 的核心模式,尽管冗长,但实际上是非常值得鼓励的。
在 Relay 中,鼓励子组件以片段的形式自行指定其数据需求。
最终,您最终会积累大量碎片,这些碎片会散布在应用程序的其他地方,因此有必要指出一些关键的 Relay 功能,说明这样做的好处:
如果您声明多个请求相同字段的片段彼此相邻,中继将不会向您的 API 发送重复请求。相反,它们都将在一次往返中获取一次。您不必担心引入过度获取/重复查询问题,因为 Relay 中不存在这些问题。
Relay 通过 Relay Compiler 引入了一个编译步骤,它可以智能地分析您的 GraphQL 架构和您在代码中定义的任何 graphql
模板标签。这会生成 artifacts,帮助管理获取数据和自动更新 Relay 存储,因此您不必这样做。通过声明大量片段,您可以有效地告诉编译器和存储组件的数据需求,即使它们相同/相似。复制是 Relay 的伟大之处。
位于树根的 QueryRenderer 祖先将处理实际的获取,并且您在树中较低的子组件上定义的片段指示中继编译器和存储在获取数据后将数据发送到何处。这是从 #2 开始的。
所以,简而言之,要充分利用 Relay,用分片声明组件的数据需求,让 Relay 完成繁重的工作,不用担心重复和缺乏可重用性。这对你有利。
【讨论】:
有替代模式吗?例如,登录用户是我知道在我的应用程序的许多不同部分中需要的东西。用于突变或过滤。我应该使用 react Context 将其存储在顶部还是将其包含在所有需要的片段中? @Batman Relay 不鼓励重用片段(如果你尝试,中继编译器会哭),特别是考虑到它如何将你的片段编译成工件,用于智能地缓存存储中的数据以备后用。 @Batman 但是,这并不意味着您不能预加载应用程序需要的查询并在其他地方访问该数据。假设您有一个useAuthedUser
钩子,它从上下文中读取有关用户当前身份验证状态的数据。然后,您可以简单地声明您的中继片段依赖项inside 的上下文提供程序,该上下文提供程序包装了您的应用程序中的所有其他内容。在这种情况下,您可以在中继中摆脱这种架构,因为您有效地描述了上下文提供者的数据需求。
我喜欢这种方法,所以基本上我可以在 AppProvider 中拥有一个 QueryRenderer,并在该渲染器中包含我认为全局重要的任何内容。从那里我可以在应用程序的任何地方访问它。我会试试这个。谢谢你的建议。以上是关于如何在不复制片段的情况下传递道具的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Typescript 在不丢失任何道具的情况下键入样式组件?
如何在不将图像保存在本地的情况下将捕获的图像(Surface View)传递给另一个片段?
如何在不连接 Powershell 的情况下传递参数? [复制]