1

I'm using Tabs from Material UI where I'm displaying a List component filtered by the tab, please see the code of the Tabs in my Container Component:

              <Tabs
                    className="DrawerTabs"
                    inkBarStyle={{ display: 'none' }}
                >
                    <Tab label="Headline"
                         data-route="/headline"
                         onActive={this.handleActive}
                         className={this.isActive('Headline')}
                    >
                        <div>
                            <ModulesListContainer
                                filter="Headline"
                            />

                        </div>
                    </Tab>
                    <Tab label="Body"
                         data-route="/body"
                         onActive={this.handleActive}
                         className={this.isActive('Body')}
                    >
                        <div>
                            <ModulesListContainer
                                filter="Body"
                            />
                        </div>
                    </Tab>
                    <Tab
                        label="Other"
                        data-route="/other"
                        onActive={this.handleActive}
                        className={this.isActive('Other')}
                    >
                        <div>
                            <ModulesListContainer
                                filter="Other"
                            />
                        </div>
                    </Tab>
                </Tabs>

and the code of the ModuleList I placed in each of the tabs which is showing only items based on the filter passed from the Container Component:

        const ModulesList = (props) => {

            let ListItems = props.modulesProps.map(module => {

                if (props.filter === module.category) {
                    return (
                        <ListItem
                            key={module.id}
                            className="ModulePreview"
                        >
                            {module.id} - {module.name} - {module.thumbnail}
                            <FontAwesome
                                name="plus-circle"
                                size="2x"
                                onClick={props.addModule.bind(this, module)}
                                className="AddModule"
                            />
                        </ListItem>
                    )
                }
            })

            return (
                <div className="ModulesList">
                    <List>
                        {ListItems}
                    </List>
                </div>
            )
        }

Even though I can see only the filtered items in each of the tabs (thus key is unique as each item is there only once) I'm still getting this warning:

Warning: flattenChildren(...): Encountered two children with the same key, 1. Child keys must be unique; when two children share a key, only the first child will be used.

Why is that?

Any help / ideas / tips would be highly appreciated.

Thanks a lot in advance! :)

Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
Michaela
  • 268
  • 2
  • 4
  • 14

1 Answers1

0

Meaning of that line is module.id is not unique, there will be 2 objects in array that have the same id=1, to avoid that you can use index of object, it will always be unique.

Use this:

let ListItemsUI = [];
props.modulesProps.forEach((module, i) => {
    if (props.filter === module.category) {
        ListItemsUI.push (
            <ListItem
                key={i}
                className="ModulePreview"
            >
                {module.id} - {module.name} - {module.thumbnail}
                <FontAwesome
                    name="plus-circle"
                    size="2x"
                    onClick={props.addModule.bind(this, module)}
                    className="AddModule"
                />
            </ListItem>
        )
    }
})

return (
     <div className="ModulesList">
          <List>
              {ListItemsUI}
          </List>
     </div>
)

One more thing map is not suitable for these cases where you want to return only few element on the basis of condition, use forEach for that. Reason is if you don't return anything, by default map will return undefined.

Check the output of this example:

let a = [1,2,3,4,5,6,7,8];

let b = a.map(el=>{
    if(el % 2 == 0)
       return el;
})

console.log(b);
Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
  • thanks for that, i'm not getting the warning anymore however every item appears 3x times because i have the element on the page three times (in each of the tabs), guess i need to prevent duplication if the element is in the array already it shouldn't be pushed again...which I could do using the id - it is unique for each module – Michaela Apr 05 '17 at 16:35
  • you have to remove the duplicate entries from array, i think. how you are prepapring that array ? – Mayank Shukla Apr 05 '17 at 16:46
  • it's just an empty array ListItems = [] then i added data-itemid={module.id} in so I can determine duplicates – Michaela Apr 06 '17 at 10:55
  • why would something like this not work? const ListItemsUnique = [] ListItems.map(item => { if (ListItemsUnique.indexOf(item.props['data-itemid']) === -1) { ListItemsUnique.push(item) } }) – Michaela Apr 06 '17 at 11:37
  • i think issue is item will be an object, and you are pushing that object in unique list, and checking the index of `data-itemid`. – Mayank Shukla Apr 06 '17 at 12:26
  • it's been answered already - http://stackoverflow.com/questions/43254382/remove-array-items-where-object-property-is-not-unique – Michaela Apr 06 '17 at 12:27