本文翻译自文章 Prop drilling and component composition in React,由公众号 ikoofe 完成翻译,点击底部 “阅读原文” 可阅读原文。本文主要介绍如何通过组合的方式来解决 React 的 prop drilling 问题。
Prop drilling 是指当上层组件中持有 state,而一个深度嵌套的组件需要使用这个 state 时,一种做法是用 props 透过中间组件一层层往下传,尽管中间组件并不需要他们。
只需要做一下重构就可以避免 prop drilling:
比如下面的 UI 结构 :
这是一个动态的 navigation(导航),Sidebar 从服务器接收数据,并根据接收的数据来渲染该 navigation。
在这个示例中,如何获取数据并不是本文的重点,因此为了便于理解,我们把用于渲染 navigation 的 JSON 数据进行简化:
[
{ "label": "Home", "href": ... },
{ "label": "About", "href": ... }
{
"label": "Account",
"sub": [
{"label": "Profile", "href": ...},
{"label": "Subscriptions", "href": ...}
]
}
];
我们需要将这些数据提供给各个组件(NavList、NavItem、SubNavList、SubNavItem)。其中的一种实现方式是将数据在组件之间层层传递。
尽管这段代码能实现我们想要的功能。然而,这种组装组件的方式会带来大量的 prop drilling。其中的每个组件都需要知道它接收了哪些 props,并且还要了解如何将这些 props 传递给子组件。即便组件不使用这些 props,却还要维护这些 props。
接下来,让我们重构这些组件,通过使用 children 来让组件更加独立:
现在,我们有了一组简单而又独立的组件,我们可以直接在 Sidebar 中渲染它们。
这么做的好处是避免了 prop drilling,这些独立的组件可以适配不同的数据结构,也可以在不同的位置重复使用。
如果我们不想直接在 Sidebar 中做数据处理,我们可以将其移动到单独的组件中。
本文主要是通过组合 (composition) 的方式来解决 prop drilling 问题。在 Sidebar 和 Dialog 等展现通用容器中,React 官方文档中建议这些组件使用一个特殊的 children prop 来将他们的子组件传递到渲染结果。也就是上面介绍的方法。
除此之外,也可以使用 React Context 或 Redux 等工具类库来避免 prop drilling,用了这些状态管理工具会让子组件依赖于父组件,导致各个组件不那么独立了,可复用性会受到影响。
关注公众号,阅读更多前端技术文章