如何避免对同一数组两次调用.map()?即使渲染组件非同级
.map() Calls Great question—iterating over the same array twice does feel unnecessary, especially as your pricepointsData grows. The core issue here is that <Tab> elements live inside <TabList> while <TabPanel> elements are direct children of <Tabs>, so you can’t render both in a single .map() pass directly. But we can fix this by pre-generating the elements we need first, then reusing them.
Here are two clean, practical approaches:
Approach 1: Pre-generate Separate Arrays with forEach
We’ll loop through the data once, building both our tab and panel element arrays upfront, then render those arrays where needed:
render() { const tabElements = []; const tabPanelElements = []; this.state.pricepointsData.forEach(pricepoint => { // Add tab to our tabs array (don't forget unique keys!) tabElements.push(<Tab className="tab" key={pricepoint.id}>{pricepoint.name}</Tab>); // Add corresponding panel to our panels array tabPanelElements.push( <TabPanel key={pricepoint.id}> <Pricepoint pricepoint={pricepoint} displayLast4={this.state.displayLast4} /> </TabPanel> ); }); return ( <div className="pricepoints-form"> <Tabs className="tabs"> <TabList>{tabElements}</TabList> {tabPanelElements} </Tabs> </div> ); }
Quick note: I added key props here—always include unique keys when rendering lists in React to avoid warnings and ensure proper component updates.
Approach 2: Map to an Object of Elements
If you prefer using .map() instead of forEach, you can create an array of objects that hold both the tab and panel for each pricepoint. The second map here is a tiny, cheap loop (compared to iterating your original data twice):
render() { // Map once to create an array of { tab, panel } objects const tabsAndPanels = this.state.pricepointsData.map(pricepoint => ({ tab: <Tab className="tab" key={pricepoint.id}>{pricepoint.name}</Tab>, panel: ( <TabPanel key={pricepoint.id}> <Pricepoint pricepoint={pricepoint} displayLast4={this.state.displayLast4} /> </TabPanel> ) })); return ( <div className="pricepoints-form"> <Tabs className="tabs"> <TabList>{tabsAndPanels.map(item => item.tab)}</TabList> {tabsAndPanels.map(item => item.panel)} </Tabs> </div> ); }
Both approaches ensure you only process your original pricepointsData once, which is more efficient—especially if your dataset is large. The first approach might feel slightly leaner since it skips the second tiny map, but in most cases, the performance difference is negligible. Pick whichever style fits your codebase better!
内容的提问来源于stack exchange,提问作者Bojan Ivanac

