react 组件中使用组件_如何避免使用组件合成在React中进行道具钻探

react 组件中使用组件

Prop Drilling is the process by which you pass data from one part of the React Component tree to another by going through other parts that do not need the data but only help in passing it around.

道具钻探是将数据从React Component树的一部分传递到另一部分的过程,该过程不需要数据,而仅有助于传递数据。

Imagine someone living in Lagos, Nigeria placing an order on Amazon for a package. The package will have to go through many hands — it has to be flown by air to Nigeria, transported to the Lagos, moved from place to place until it gets into the hands of the buyer. At each stage, Amazon employs the services of people that do not ‘care’ about the product, they only help to ‘pass’ it to the person who cared — the buyer.

想象一下住在尼日利亚拉各斯的某人向亚马逊订购了包裹。 这个包裹必须要经过很多人的手–它必须空运到尼日利亚,然后运到拉各斯,从一个地方搬到另一个地方,直到到达买家手中。 在每个阶段,亚马逊都会雇用不关心产品的人们提供服务,他们只会帮助将产品“传递”给关心的人,即购买者。

Prop drilling is similar: You pass data (props) from some FirstComponent to another SecondComponent— which doesn’t need the data to render but only passes it to another ThirdComponent, which also doesn’t need it and may pass it to another FourthComponent. This may continue until the data gets to the ComponentNeedingProps.

道具钻探与此类似:您将数据(道具)从某个FirstComponent到另一个SecondComponent -不需要呈现数据,而仅将其传递给另一个ThirdComponent ,后者也不需要它,并且可以将其传递给另一个FourthComponent 。 这可能会一直持续到数据到达ComponentNeedingProps为止。

Consider the code snippet below:

考虑下面的代码片段:

The content prop is passed to FirstComponent in the root component, App. But FirstComponent does not need the prop to render, it only passes it to SecondComponent, which passes it to ThirdComponent, which passes it to ComponentNeedingProps. It is this component that uses the content prop to render content in <h3>{content}</h3>.

content道具将传递到根组件App中的FirstComponent 。 但是FirstComponent不需要道具来渲染,它仅将其传递给SecondComponent ,后者将其传递给ThirdComponent ,后者将其传递给ComponentNeedingProps 。 正是此组件使用content属性在<h3>{content}</h3>呈现内容。

为什么道具钻探有问题? (Why is Prop Drilling a Problem?)

Prop drilling doesn’t have to be a problem. If we are passing data only between 2 or 3 levels, we are fine. It will be easy to trace the flow of data. But imagine, we are drilling 5 levels, or 10 levels, or 15.

道具钻探不一定是问题。 如果我们仅在2或3级之间传递数据,那很好。 跟踪数据流将很容易。 但是想象一下,我们正在钻5个级别或10个级别或15个级别。

Image for post

如何解决问题 (How to Solve the Problem)

Prop drilling is not a new problem in React (quite obviously), and there have been many solutions that let us pass data down to deeply nested Components.

在React中,支持钻探并不是一个新问题(很明显),并且有许多解决方案可以让我们将数据向下传递到深度嵌套的组件中。

One of which is Redux: You create a data store and connect any component to the store and voila, no matter where the component is positioned in the Component Tree it has access to the store.

Redux就是其中之一:创建数据store connect任何组件connectstore ,瞧,无论该组件在组件树中的位置如何,它都可以访问该存储。

React also has the concept of Context which lets you create something like a global data store and any Component in 'context' can have access to the data store.

React还具有Context的概念,它使您可以创建全局data store类的东西,并且“上下文”中的任何组件都可以访问该数据存储。

If you however want to solve this problem without using context, you can use Component Composition as suggested by the React Docs:

但是,如果您想在不使用context的情况下解决此问题,则可以使用React Docs建议的Component Composition

If you only want to avoid passing some props through many levels, component composition is often a simpler solution than context

如果您只想避免某些道具通过多个级别,则组件组合通常是比上下文更简单的解决方案

You can learn more here Before You Use Context and also, check out Michael Jackson’s thread on why you should avoid using the Context API.

您可以在此处了解更多信息, 然后再使用上下文 ;此外,请查看Michael Jackson的主题,以了解为什么应避免使用Context API。

如何避免使用零部件成分进行支撑钻 (How to Avoid Prop Drilling Using Component Composition)

Component Composition is when you compose different Components, usually simple, together to create more complex functionality. If you have ever written a React app, I bet that you have been composing components. Take for example:

组件组合是指将通常简单的不同组件组合在一起以创建更复杂的功能时。 如果您曾经编写过React应用程序,那么我敢打赌,您一直在编写组件。 举个例子:

function LoginForm(props){
return (
<Input name="fname" />
<Button onClick={props.handleClick} />)
}

Here, by using composition we are creating a ‘complex’ functionality, LoginForm by composing two simpler functionalities, Button and Input components. You can read more on the composition on React documentation page.

在这里,通过使用组合,我们通过组合两个更简单的功能( ButtonInput组件)来创建“复杂”功能LoginForm 。 您可以在React 文档页面上的组成中阅读更多内容。

我们要解决的实际问题是什么? (What is the actual problem we are trying to solve?)

The actual problem is that we want ComponentNeedingProps to be rendered in ThirdComponent but it needs data from the root component, App to do so. In other words, ComponentNeedingProps needs data from somewhere higher in the Component Tree (App) from where it is rendered (ThirdComponent).

实际的问题是我们希望ComponentNeedingPropsThirdComponent呈现,但它需要来自根组件App数据。 换句话说, ComponentNeedingProps需要来自组件树( App )中更高的位置( ThirdComponent )的数据。

The Solution?

解决方案?

儿童道具的不受约束的力量 (The untamed powers of the children prop)

You can compose components by making one a child of another, for example:

您可以通过使一个子组件成为另一个子组件来组成组件,例如:

<ReactComponent1>
<ReactComponent2 />
</ReactCompoent1>

ReactComponent2 is invoked inside of ReactComponent1 and hence it is a child of it. Every component has an ‘automatic’ prop named children that holds the children of the Component. So in ReactComponent1 we can write:

ReactComponent2ReactComponent1内部被调用,因此它是它的子代。 每个组件都有一个名为children的“自动”道具,该道具持有该子代的子代。 因此,在ReactComponent1我们可以编写:

function ReactComponent1({ children }) {
return
(<div> I render my children
{children}
</div>)
}

How can we use it in this case? Remember we want ComponentNeedingProps to be rendered in another component down in the Component Tree, if we can pass ComponentNeedingProps as a child component with the data it needs and then render it in its parent then we have successfully avoided prop drilling.

在这种情况下,我们如何使用它? 请记住,我们希望将ComponentNeedingProps呈现在组件树中的另一个组件中,如果我们可以将ComponentNeedingProps作为其所需数据的子组件传递,然后在其父项中呈现,则我们已经成功避免了prop钻探。

So, we will have:

因此,我们将拥有:

<ThirdComponent>
<h3>I am the third component</h3>
<ComponentNeedingProps content={content} />
</ThirdCompoent>

And in the declaration of ThirdComponent we have:

ThirdComponent的声明中,我们有:

function ThirdComponent({ children }) {
return (
<div>
<h3>I am the third component</h3>
{children}
</div>
);
}

This doesn’t look much different from what we had earlier but wait for the magic.

这看起来与我们之前的内容没有太大不同,但请耐心等待。

By following this technique of rendering children, we can refactor App to this:

通过遵循这种渲染子级的技术,我们可以将App重构为:

function App() {
const content = "Who needs me?";
return (
<div className="App">
<FirstComponent>
<SecondComponent>
<ThirdComponent>
<ComponentNeedingProps content={content} />
<ThirdComponent>
</SecondComponent>
</FirstComponent>
</div>
);
}

Then we refactor each of the other components to render their children

然后,我们重构其他每个组件以呈现其children

FirstComponent:

FirstComponent:

function FirstComponent({ children }) {
return (
<div>
<h3>I am the first component</h3>;
{ children }
</div>
);
}

SecondComponent:

SecondComponent:

function SecondComponent({ children }) {
return (
<div>
<h3>I am the second component</h3>;
{children}
</div>
);
}

ThirdComponent:

ThirdComponent:

function ThirdComponent({ children }) {
return (
<div>
<h3>I am the third component</h3>
{children}
</div>
);
}

ComponentNeedingProps stays as it is:

ComponentNeedingProps保持不变:

function ComponentNeedingProps({ content }) {
return <h3>{content}</h3>
}

Did you see it? We have avoided prop drilling by giving ComponentNeedingProps the data it needs right from the source of the data App and then by using the children prop, we passed it down to where it should be rendered, ThirdComponent.

你看见了吗? 我们通过从数据App的源直接为ComponentNeedingProps提供所需的数据,然后通过使用子道具,将其传递到应呈现的位置ThirdComponent来避免道具钻探。

Awesome. See the complete code:

太棒了 查看完整的代码:

什么时候应该使用Context API? (When should you use the Context API?)

You can also use the Context API to avoid prop drilling and I may write another article on that in the nearest future.

您还可以使用Context API来避免道具钻探,我可能会在不久的将来对此发表另一篇文章。

If you need to have some data accessible by many components at different nesting levels, then you should use the Context API. React docs advises that we ‘apply it sparingly because it makes component reuse more difficult.’ In other words, you might not be able to reuse your components ‘out of context’.

如果需要让不同嵌套级别的许多组件可以访问某些数据,则应使用Context API。 React docs建议我们“谨慎地应用它,因为这会使组件重用变得更加困难”。 换句话说,您可能无法“脱离上下文”重用组件。

That is it for this post, thank you for reading through. You can play with the code on CodeSandbox

这篇文章就是这样,谢谢您的通读。 您可以在CodeSandbox上使用代码

Happy Coding.

编码愉快。

Note: This post has had to go through major revisions based on the feedback provided in the comments. I am grateful for all the people who provided useful feedback. Some of the comments below do not apply to this revision.

注意 :这篇文章必须根据评论中提供的反馈进行重大修订。 感谢所有提供有用反馈的人们。 以下某些注释不适用于此修订版。

翻译自: https://medium.com/javascript-in-plain-english/how-to-avoid-prop-drilling-in-react-using-component-composition-c42adfcdde1b

react 组件中使用组件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值