React: Warning: Each child in a list should have a unique "key" prop

I'm experiencing this warning with different components in my application but I will take just the following one as example.

I have got the following component. It has a map function that renders multiple components from an array:

const Clipboards = () => {
    const { user, addClipboard } = useAuth();
    
    const clipboards = user?.clipboards || [];
    return (
        <>
            {clipboards.map(clipboard =>
                <Clipboard clipboard={clipboard}/>
            )}
            <IconButton  onClick={() => addClipboard()} color={'secondary'}>
                <PlusIcon/>
            </IconButton>
        
        </>
    )
};

export default Clipboards;

with Clipboard being as follows. As you can see, I use key prop in the wrapping div:

const Clipboard = ({clipboard, setSelectedClipboard}) => {
    const {addClipboardRubric} = useAuth();
    const {enqueueSnackbar} = useSnackbar();
    
    const selectClip = () => {
        setSelectedClipboard({id: clipboard.id, name: clipboard.name})
    };
    
    const [{isActive}, drop] = useDrop(() => ({
        accept: 'rubric',
        collect: (monitor) => ({
            isActive: monitor.canDrop() && monitor.isOver(),
        }),
        drop(item, monitor) {
            handleDrop(item)
        },
    }));
    
    const handleDrop = async (rubric) => {
        try {
            await addClipboardRubric({
                clipboardId: clipboard.id,
                rubric: rubric
            })
            enqueueSnackbar('Rubric added', {
                variant: 'success'
            });
        } catch (e) {
            enqueueSnackbar('Rubric already added', {
                variant: 'error'
            });
        }
        
    }
    console.log(`clip-${clipboard.id}`)
    return (
        <div ref={drop} key={clipboard.id}>
            <IconButton
                id={`clip-${clipboard.id}`}
                onClick={selectClip}
                color={'secondary'}
            >
                <Badge badgeContent={clipboard?.rubrics?.length || 0} color={"secondary"}>
                    <ClipboardIcon/>
                </Badge>
            </IconButton>
        </div>
    )
}

export default connect(
    ({search: {repertories = {}}}) => ({repertories}),
    (dispatch) => ({
        setSelectedClipboard: (payload) => dispatch(SET_SELECTED_CLIPBOARD(payload)),
    })
)(Clipboard);

As you can see. I'm adding the key and it is unique. What would be the problem then?

showing unique keys

Upvotes: 0

Views: 68

Answers (2)

Sanan Ali
Sanan Ali

Reputation: 3444

You have to add a unique key to every item returned from the map function. For example, you can use the index as a unique key which is not recommended but just to give you an example. In your code, you are adding a key inside the component. You need to add the key to the component itself. Check the below code.

const Clipboards = () => {
    const { user, addClipboard } = useAuth();
    
    const clipboards = user?.clipboards || [];
    return (
        <>
            {clipboards.map((clipboard,index) =>
                <Clipboard clipboard={clipboard} key={index}/>
            )}
            <IconButton  onClick={() => addClipboard()} color={'secondary'}>
                <PlusIcon/>
            </IconButton>
        
        </>
    )
};

export default Clipboards;

Upvotes: 2

user3536141
user3536141

Reputation: 53

You haven't added a key to the Clipboard component which is returned by the map.

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity.

Source

Try something like this (if Clipboard as an id property):

{clipboards.map(clipboard =>
  <Clipboard key={clipboard.id} clipboard={clipboard}/>
)}

Read this before using the index as a key

Upvotes: 1

Related Questions