React props:我应该传递对象或其属性吗?有什么区别吗?

时间:2018-10-03 06:45:08

标签: javascript reactjs react-props

传递道具时,应该将整个对象传递到子组件中,还是应该先在父组件中单独创建道具,然后再将这些道具传递给子组件?

传递整个对象

<InnerComponent object={object} />

分别创建首先需要的道具:

<InnerComponent name={object.name} image={object.image} />

哪个是首选,并且取决于它,我应该使用哪个作为量规?

8 个答案:

答案 0 :(得分:2)

您应该更喜欢第二个示例,以单独传递道具。 在这里,您可以清楚地看到传递了哪些参数,并可以快速与期望的参数进行比较。这使人们之间的协作更加容易,并使应用程序的状态更加清晰。

如果不需要,我个人试图避免传递整个对象。 就像散布运算符一样,里面可以有任何属性,在更大的范围内调试起来要困难得多。

一些纯粹的反应,例如prop-typestypescript可能有助于在大型应用程序中定义明确和预期的属性

答案 1 :(得分:1)

将多个道具传递给子组件是将道具传递给子组件的首选方式。这将帮助您跟踪子组件中应用程序的状态。 另外,请随时使用$(window).bind("load", function() { var ws = new WebSocket("wss://www.bitmex.com/realtime?subscribe=trade:XBTUSD"); ws.onopen = function(){ ws.send(JSON.stringify({"trade":"XBTUSD"})) }; ws.onmessage = function (msg){ var resp = JSON.parse(msg.data); console.log(resp); var price = resp['data'][0].price; // can not read property 0 of undefined :/ console.log('Price is : ' + price); }; }); 模块。它的行为类似于Java中的泛型,并为道具传入提供了类型安全性。

答案 2 :(得分:1)

如果您没有利用对象中的所有属性,则最好单独传递所需的属性,因为当Child组件使用PureComponent时,它可以帮助优化性能。 shouldComponentUpdate。在这种情况下,仅当Child组件使用的道具发生更改时,它才会重新渲染,而当对象内部的未使用属性发生更改时,则不会重新渲染。

但是,如果您要利用对象中的所有属性,只要您正确处理了对象的变异,那么将对象作为道具传递给对象就不会产生太大的差异。

答案 3 :(得分:1)

由于JavaScript没有类型注释,因此第二种选择会更可取,如@mstruebing所提到的那样,代码将更易于维护。但是,如果您使用的是TypeScript React(支持类型注释),则两种选择都将一目了然。但是请记住,首选是促进视图和模型之间的紧密耦合,这使您无需键入太多内容即可进行快速开发。第二种选择可能会减慢开发速度,但您具有更高的灵活性和对未来更改的承受能力。

因此,衡量标准是:如果您偏向于选择开发速度而不是灵活性,那么请选择1;如果您喜欢灵活性而不是开发速度,请选择2。

额外笔记

好吧,我们什么时候应该优先考虑开发速度而不是灵活性?这是我的2美分。

如果您的项目是短期使用的(例如,开发仅在选举期间收集选票的应用程序),那么请首选。

如果您的项目打算长期使用(例如,在线银行交易门户网站),则应选择第二个选项。

答案 4 :(得分:1)

取决于该对象。您是否需要将其所有属性都传递给另一个组件?或者...您可能需要将5个属性中的2个传递给特定组件?

  • 如果您不需要传递其所有属性,建议您传递 PropertiesProps
  • 但是,如果您100%确定需要将所有属性 一起传递,我建议将整个Object作为Props传递给 那样的话,因为代码会更清晰,使您远离 忘记传递一些东西。例如;当您添加新属性时 传递给该对象,您不必传递它,因为您已经传递了 整个对象!

好吧,如果您不确定该对象的当前/未来用途,因为您可能需要尽快排除某些属性,那么在这种情况下,您应该单独传递其属性,而不是将一些未使用的属性传递给其他组件。

答案 5 :(得分:1)

根据the principle of least privilege,这是一种正确的方法:

<InnerComponent name={object.name} image={object.image} />

这限制了InnerComponent意外修改原始对象或访问不适合原始对象的属性。

或者,可以从原始对象中选取属性,并将其作为props传递:

<InnerComponent {...pick(object, 'name', 'image')} />

如果列出许多繁琐的属性,则可能有一个接受对象的道具:

<InnerComponent object={pick(object, 'name', 'image')} />

答案 6 :(得分:1)

我同意其他答案,简而言之,这取决于,其他答案中提出的观点都是有效的。

我想补充的其他一些也倾向于使用单个属性的要点如下 -

  • 有时甚至不是我是否需要所有属性的问题?这应该是更多的问题 - 我是否想将组件的使用限制为只有完整的对象而不仅仅是属性的子集。

以一个小部件为例,它显示汽车的图像、品牌和型号作为小部件列表的一部分,期望 full Car 类型在为了仅显示汽车的图像、品牌和型号。仅需要这 3 个属性。

  • 随着 graphql 之类的兴起,我们可以限制返回的关于类型的数据的属性,我们不应该总是假设组件可以访问基于类型的完全填充的对象。

  • 最后,关于导致树下组件不必要的重新渲染,总是传递完整的对象,您可能会导致所有使用该对象的子级在对象更新时重新渲染。然而,将单独的属性传递给孩子,通常是原语,我们可以更好地减少不必要的重新渲染

答案 7 :(得分:1)

对象的全部意义在于将相似的属性封装在一起。如果您有大约 10 个属性并希望在您的子组件中使用它们,请坚持使用对象。

但在您的情况下,我的意见是使用您的第二个示例,因为它使子组件中的代码更简单。

为了两全其美,只需解构您在子组件中需要的那些道具。

像这样:

function InnerComponent({ name, image }) {
  ...
}

如果您不喜欢参数中的大括号,请执行以下操作:

function InnerComponent(props) {
  const { name, image } = props;
  ...
}