简体   繁体   English

在 React 的渲染中传播组件数组

[英]Spread an array of components in render in React

I currently render an array of component as child of another component like this:我目前将一个组件数组渲染为另一个组件的子组件,如下所示:

const myComponents = [
  <div key='1'>Component 1</div>,
  <div key='2'>Component 2</div>,
  <div key='3'>Component 3</div>,
];

render() {
  return (
    <AnotherComponent>
      {myComponents}
      <div>Another element</div>
    </ AnotherComponent>
  )
}

My issue is that inside AnotherComponent , my array of components is rendered as an array (which makes sense):我的问题是在AnotherComponent内部,我的组件数组被呈现为一个数组(这是有道理的):

// Inside AnotherComponent
console.log(this.props.children) // [[ {}, {}, {} ], {} ]

My expected output is that components should be "spread", like this:我预期的 output 是组件应该“散布”,如下所示:

// Inside AnotherComponent
console.log(this.props.children) // [ {}, {}, {}, {} ]

I have tried to map the components in the render but the output is the same:我尝试过map渲染中的组件,但 output 是相同的:

const myComponents = [
  ...
];

render() {
  return (
    <AnotherComponent>
      {myComponents.map(component => component)}
      <div>Another element</div>
    </ AnotherComponent>
  )
}

I can achieve that with flattening my array of children inside AnotherComponent .我可以通过在AnotherComponent中展平我的子数组来实现这一点。 But I was wondering if there was a syntax that would allow me to flatten it before, so that AnotherComponent is cleaner.但我想知道是否有一种语法可以让我之前将其展平,以便使AnotherComponent更干净。

Reason I want to achieve this is because I do some complex layout rendering inside AnotherComponent .我想要实现这一点的原因是因为我在AnotherComponent中进行了一些复杂的布局渲染。 This requires the children not to be arrays, unless I explicitly want it, which is not the case here.这要求孩子不要是 arrays,除非我明确想要它,这里不是这种情况。

Edit: Here is a demo with my current output and my expected output:编辑:这是我当前的 output 和我预期的 output 的演示:

 const components = [ <div>Component 1</div>, <div>Component 2</div>, <div>Component 3</div>, ]; const MyLayoutComponent = ({ children }) => { console.log('❌ Current output', children); console.log('✅ Expected output', children.flat()); return <div>{children}</div> } const App = () => ( <MyLayoutComponent> {components} <div>Some other component</div> </MyLayoutComponent> ); ReactDOM.render(<App />, document.body)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.production.min.js"></script>

Try concat() method.尝试 concat() 方法。

const App = () => (
  <MyLayoutComponent>
    {components.concat(<div>Some other component</div>)}
  </MyLayoutComponent>
);

It will concat your array with other component.它会将您的数组与其他组件连接起来。

在此处输入图像描述

The fact that they come through as an array is appropriate, and useful because React can optimize re-rendering if the order of the list changes based on the key attribute.它们以数组形式出现的事实是适当且有用的,因为如果列表的顺序基于key属性发生变化,React 可以优化重新渲染。 It's the fact they're in an array that makes React look for a key.正是它们在一个数组中,这使得 React 寻找一个键。

If you don't want them to be a list, per se, you could use a fragment instead:如果您不希望它们本身成为列表,则可以使用片段代替:

const myComponents = <>
  <div>Component 1</div>
  <div>Component 2</div>
  <div>Component 3</div>
</>;

That will still come through as a single entry in props.children , but that entry will be a fragment, not an array, and React won't require keys on it, etc.这仍然会作为props.children中的单个条目出现,但该条目将是一个片段,而不是一个数组,并且 React 不需要它上面的键,等等。

The only other answers I can think of are to put your other components in an array as well (but that will require they have a key ):我能想到的唯一其他答案是将您的其他组件也放入一个数组中(但这需要它们有一个key ):

const App = () => (
  <MyLayoutComponent>
    {[...components, <div key="other">Some other component</div>]}
  </MyLayoutComponent>
);

 const components = [ <div>Component 1</div>, <div>Component 2</div>, <div>Component 3</div>, ]; const MyLayoutComponent = ({ children }) => { console.log('✅ Current child count', children.length); console.log('✅ Expected child count', children.flat().length); return <div>{children}</div> } const App = () => ( <MyLayoutComponent> {[...components, <div key="other">Some other component</div>]} </MyLayoutComponent> ); ReactDOM.render(<App />, document.getElementById("root"));
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.production.min.js"></script>

Or to ditch JSX for this one case and write the createElement call directly:或者在这种情况下放弃 JSX 并直接编写createElement调用:

const App = () => React.createElement(
  MyLayoutComponent,
  {
    children: [
      ...components,
      <div>Some other component</div>
    ]
  }
);

 const components = [ <div>Component 1</div>, <div>Component 2</div>, <div>Component 3</div>, ]; const MyLayoutComponent = ({ children }) => { console.log('✅ Current child count', children.length); console.log('✅ Expected child count', children.flat().length); return <div>{children}</div> } const App = () => React.createElement( MyLayoutComponent, { children: [...components, <div>Some other component</div> ] } ); ReactDOM.render(<App />, document.getElementById("root"));
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.production.min.js"></script>

I can't think of a JSX way to do that.我想不出一个 JSX 方法来做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM