0

I am having difficulty in a nested loop. My data is like this. You can see in the comment in the middle of my table, I tried to loop again the 'detail_info' but I can't make it. Please check the picture example output below the code.

I can't make the third loop in my second loop. Error says: JSX expressions must have one parent element.

const data = 
  [{
     'product': {'value': 'Cotton'},
     'detail': [{'document_no': 'DO234','quantity': '55',
              'detail_info':[{'id': '1','expiry_date': '2018/10/12'},
                            {'id': '2','expiry_date': '2019/9/9'}]
              }]
  }]
     <table className='scroll-table'>
                <thead style={{'display':'table','width':'100%'}}> 
                    <tr> 
                        <th style={{'width':'20%'}}>Product</th>
                        <th style={{'width':'8%'}}>Doc. No</th>
                        <th style={{'width':'8%'}}>Quantity</th>
                    </tr>
                </thead>
                {data.map((item,idx)=>{
                    return(
                    <tbody key={idx} className="scrollbar">
                       <tr>
                        <td style={{'width':'2%'}}><input name="product" type="text" /></td>
                       </tr>
                     {item.detail.map((i,index)=>{
                         return(
                             <tr key={index} >
                                 <td colSpan="2"></td>
                                 <td>{i.document_no}</td>
                                 <td >{i.quantity}</td>
                             </tr>
                         /*  I want to loop here to make another <tr> but I 
                           cant because **JSX expressions must have one parent element. 

                            {i.detail_info.map((a,b)=>{
                            return( 
                             <tr key={b}><td>{a.expiryDate}</td></tr>
                             )})
                         */
                         )
                     })
                </tbody>
                    )
                })}
            </table>

It should look like this.

enter image description here

Vikas Singh
  • 1,791
  • 1
  • 14
  • 26
bossajie
  • 328
  • 3
  • 16
  • Which version of react are you using – Shubham Khatri Dec 12 '18 at 10:07
  • You can use `` for wrapping both `` if you are using a new version of React. – Ana Liza Pandac Dec 12 '18 at 10:08
  • @ShubhamKhatri I am using react 0.14.7, I can't yet upgrade it to the latest because it is connected to our backend django and there are lot of dependencies also that are also conflict when I tried to update the version of my react. – bossajie Dec 12 '18 at 10:09
  • check https://stackoverflow.com/questions/45339086/warning-validatedomnesting-div-cannot-appear-as-a-child-of-tbody/45341901#45341901 – Shubham Khatri Dec 12 '18 at 10:12
  • Would you think guys `` is the solution for this? – bossajie Dec 12 '18 at 10:13
  • @ajiejot if you use the latest version then yes, but the link that I just commented also has an alternative solution using JSX syntactic sugar. With the version of react that you use, that would be the appropriate solution for you – Shubham Khatri Dec 12 '18 at 10:18
  • I'll try it. I am now configuring my webpack, so many dependencies affected since I updated my react version. I'll inform you guys when I already figured it out. Thanks – bossajie Dec 12 '18 at 11:14
  • @ShubhamKhatri Hi guys, it's working now in latest version (react 16) but some of my project/components conflict in react 16, do you have any idea how to fix this in 0.14.7 version of React? – bossajie Dec 27 '18 at 03:39
  • return an array of elements separated by comma – Shubham Khatri Dec 27 '18 at 05:01
  • Got it! Thank you so much @ShubhamKhatri. – bossajie Dec 27 '18 at 06:42

1 Answers1

0

When you return a JSX expression, there may only be one parent element. Assuming you are using React v16, you may accomplish your task by wrapping your <tr/>'s in a fragment like:

{item.detail.map((i, index) => (
    <Fragment>
        <tr key={index}>
            <td colSpan="2"></td>
            <td>{i.document_no}</td>
            <td>{i.quantity}</td>
        </tr>
        {i.detail_info.map((a, b) => <tr key={b}>
            <td>{a.expiryDate}</td>
        </tr>)
        }
    </Fragment>
))

By wrapping your <tr/> with a <Fragment/> your JSX expression will have one parent elment. Please see React Fragments.

Miroslav Glamuzina
  • 4,472
  • 2
  • 19
  • 33