最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Spread an array of components in render in React - Stack Overflow

programmeradmin6浏览0评论

I currently render an array of ponent as child of another ponent 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 ponents is rendered as an array (which makes sense):

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

My expected output is that ponents should be "spread", like this:

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

I have tried to map the ponents in the render but the output is the same:

const myComponents = [
  ...
];

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

I can achieve that with flattening my array of children inside AnotherComponent. But I was wondering if there was a syntax that would allow me to flatten it before, so that AnotherComponent is cleaner.

Reason I want to achieve this is because I do some plex layout rendering inside AnotherComponent. This requires the children not to be arrays, unless I explicitly want it, which is not the case here.

Edit: Here is a demo with my current output and my expected output:

const ponents = [
  <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>
    {ponents}
    <div>Some other ponent</div>
  </MyLayoutComponent>
);

ReactDOM.render(<App />, document.body)
<script src=".0.0/umd/react.production.min.js"></script>
<script src=".0.0/umd/react-dom.production.min.js"></script>

I currently render an array of ponent as child of another ponent 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 ponents is rendered as an array (which makes sense):

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

My expected output is that ponents should be "spread", like this:

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

I have tried to map the ponents in the render but the output is the same:

const myComponents = [
  ...
];

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

I can achieve that with flattening my array of children inside AnotherComponent. But I was wondering if there was a syntax that would allow me to flatten it before, so that AnotherComponent is cleaner.

Reason I want to achieve this is because I do some plex layout rendering inside AnotherComponent. This requires the children not to be arrays, unless I explicitly want it, which is not the case here.

Edit: Here is a demo with my current output and my expected output:

const ponents = [
  <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>
    {ponents}
    <div>Some other ponent</div>
  </MyLayoutComponent>
);

ReactDOM.render(<App />, document.body)
<script src="https://cdnjs.cloudflare./ajax/libs/react/16.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.0.0/umd/react-dom.production.min.js"></script>

Share Improve this question edited Apr 28, 2020 at 8:04 neiya asked Apr 28, 2020 at 6:53 neiyaneiya 3,1824 gold badges26 silver badges36 bronze badges 9
  • Your code is working fine as the expected output. Please create a small demo for this to show the issue happening. – palaѕн Commented Apr 28, 2020 at 7:05
  • I edited with a demo of the issue – neiya Commented Apr 28, 2020 at 7:09
  • Even in your demo, the children is an array and not an array of arrays – Shubham Khatri Commented Apr 28, 2020 at 7:15
  • Sorry, I made the example too minimal so the problem was not visible. If I have other elements rendered you can see that the arrary is rendered as an array – neiya Commented Apr 28, 2020 at 7:22
  • 1 @T.J.Crowder sorry, I am not used tot stack snippets, it's done now :) – neiya Commented Apr 28, 2020 at 8:05
 |  Show 4 more ments

2 Answers 2

Reset to default 3

The fact that they e 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. It's the fact they're in an array that makes React look for a key.

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 e 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.

The only other answers I can think of are to put your other ponents in an array as well (but that will require they have a key):

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

const ponents = [
  <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>
    {[...ponents, <div key="other">Some other ponent</div>]}
  </MyLayoutComponent>
);

ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare./ajax/libs/react/16.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./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:

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

const ponents = [
  <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: [
      ...ponents,
      <div>Some other ponent</div>
    ]
  }
);

ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare./ajax/libs/react/16.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./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.

Try concat() method.

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

It will concat your array with other ponent.

发布评论

评论列表(0)

  1. 暂无评论