I am storing an array in state and looping over it to display content on my website.
This is the function that I am calling to loop over the array stored in state:
displayRefundSearchResults2 = () => {
let refundSearchMatch = this.state.refundSearchMatch
if(refundSearchMatch.length === 0){return}
refundSearchMatch = refundSearchMatch.map(e => {e.userEvent = this.state.myEvent; return e})
console.log('refundSearchMatch', refundSearchMatch.map(e => e._id), refundSearchMatch.map(e => e.checkedIn), '---------')
return (<>{refundSearchMatch.map((ticket, index)=> {
return( <div key={index}>
<PurchasedTicket
ticket = {JSON.parse(JSON.stringify(ticket))}
requestFromOrganiser = {true}
index={index}
/>
</div>)}
)}</>)
}
and this is the child component's code:
const PurchasedTicket = (props) =>{
return(
<div className={'ticket-detail ticket-detail-price'}>
<span>{'Ticket ID'}</span>
<h2>{ticket._id}</h2>
<span>{'Checked In'}</span>
<h2>{String(ticket.checkedIn)}</h2>
<span>{'--------'}</span>
</div>
)
}
export default withRouter(PurchasedTicket);
The data from the console.log matches perfectly with what shows up on screen at first:
refundSearchMatch (4) ['62e6ba84dd5e8206c7b6c969', '62e6ba84dd5e8206c7b6c96c', '62e6ba84dd5e8206c7b6c963', '62e6ba84dd5e8206c7b6c964'] (4) [false, false, false, false] ---------
When I tick the checkbox I have coded so that an additional element is added to the array in state.
Now, the data from the console.log and the data on screen are different:
refundSearchMatch (5) ['62e6ba84dd5e8206c7b6c969', '62e6ba84dd5e8206c7b6c96c', '62e6ba84dd5e8206c7b6c965', '62e6ba84dd5e8206c7b6c963', '62e6ba84dd5e8206c7b6c964'] (5) [false, false, true, false, false] ---------
React appears to be taking a short cut. It sees that there is an extra element in the array and it just displays the final element again. However, the new element was inserted into the middle of the array. This element is not displayed at all and the final element is duplicated instead.
How can I ensure react loops over the full contents of the array the second time?
CodePudding user response:
The key
required in a list of JSX elements is used for React to uniquely identify each component.
Think about it this way - React is given a list of 5 of component A
, each with their own props. The next render, you want to remove one of those elements and add another one. React still sees 5 instances of component A
; it has no good way of knowing that one should be removed and a new one should be added. So React just assumes they're all the same from before and only adjusts props for re-renders.
This causes issues like the one you are seeing. The fix is simple - provide React a better identifier for each component (like the ticket ID). This will help React understand when components should re-render vs when they should actually be removed or added.