Home > database >  Each child in a list should have a unique "key" prop Error
Each child in a list should have a unique "key" prop Error

Time:10-12

Currently I am working on a project using React, Next.js and Ant-Design.

While working on my project, I got an error because I didn't use a unique key like this:

Below is the detailed error log.

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

Check the render method of `ForwardRef`. It was passed a child from BoardCard. See https://reactjs.org/link/warning-keys for more information.
    at eval (webpack-internal:///./node_modules/antd/es/popover/index.js:30:31)
    at eval (webpack-internal:///./node_modules/antd/es/card/Card.js:58:62)
    at article
    at BoardCard (webpack-internal:///./components/MyPage/BoardCard.js:34:19)
    at li
    at InternalItem (webpack-internal:///./node_modules/antd/es/list/Item.js:65:31)
    at ul
    at div
    at div
    at Spin (webpack-internal:///./node_modules/antd/es/spin/index.js:94:90)
    at SpinFC (webpack-internal:///./node_modules/antd/es/spin/index.js:222:34)
    at div
    at List (webpack-internal:///./node_modules/antd/es/list/index.js:58:26)
    at section
    at BoardList (webpack-internal:///./components/MyPage/BoardList.js:22:78)
    at section
    at MyBoard
    at section
    at MyInfo
    at header
    at O (webpack-internal:///./node_modules/styled-components/dist/styled-components.browser.esm.js:31:19811)
    at AppLayout (webpack-internal:///./components/AppLayout/index.js:28:23)
    at profile
    at App (webpack-internal:///./pages/_app.js:28:24)
    at Provider (webpack-internal:///./node_modules/react-redux/es/components/Provider.js:13:3)
    at Wrapper (webpack-internal:///./node_modules/next-redux-wrapper/es6/index.js:184:35)
    at ErrorBoundary (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/client.js:8:20746)
    at ReactDevOverlay (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/client.js:8:23395)
    at Container (webpack-internal:///./node_modules/next/dist/client/index.js:241:5)
    at AppContainer (webpack-internal:///./node_modules/next/dist/client/index.js:833:24)
    at Root (webpack-internal:///./node_modules/next/dist/client/index.js:986:26)

As a result of checking the error log, it was confirmed that the error occurred in the Boardlist and BoardCard components.

So I checked the key of the relevant component, but I am using a unique key.

import React from 'react';
import { useSelector } from 'react-redux';
import { List } from 'antd';

import BoardCard from './BoardCard';

const BoardList = () => {
  const { boardPosts } = useSelector((state) => state.user);

  return (
    <section>
      <List  
          itemLayout="vertical"
          bordered    
          size="large"
          pagination={{
            onChange: (page) => console.log(page), pageSize: 3,
          }}
          dataSource={boardPosts}    
          renderItem={(item) => (  
            <List.Item>
              <BoardCard post={item} key={item.id}/>
            </List.Item>         
        )}
      />          
    </section>
  )
};

export default BoardList;
import React, { useState, useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Card, Modal, Button, Popover, Row, Col, message } from 'antd';
import PropTypes from 'prop-types';

import PostModal from '../Modal/PostModal';
import PostDeleteModal from '../HomePost/PostDeleteModal';
import { 
  likePostRequestAction, unLikePostRequestAction, 
  moveToCommentRequestAction, returnToCommentRequestAction 
} from '../../reducers/post';
import {
  BoardCardHeader, BoardCardBody, MoreIcon, ColWrapper, CardTextWrapper, 
  CardTitle, CardText, CardContent, HeaderBtn, TwoToneHeartBtnIcon, 
  HeartBtnIcon, CommentBtnIcon, CardImageWrapper, ImageWrapper 
} from './styles';

const BoardCard = ({ post }) => {
  const dispatch = useDispatch();    
  const [visible, setVisible] = useState(false);
  const id = useSelector((state) => state.user.me.id);
  const liked = post.Likers.find((v) => v.id === id);
  
  const onLikePost = useCallback(() => {
    dispatch(likePostRequestAction(post.id));    
  }, []);

  const unLikePost = useCallback(() => {
    dispatch(unLikePostRequestAction(post.id));
  }, []);
  
  const showPostModal = useCallback(() => {
    setVisible(true);
  }, []);

  const boardCardCommentBtn = useCallback(() => {
    setVisible(true);
    dispatch(moveToCommentRequestAction());
  }, []);

  const boardmodalOkBtn = useCallback(() => {    
    setVisible(false);
    dispatch(returnToCommentRequestAction());              
  }, []);

  const boardmodalCancelBtn = useCallback(() => {    
    setVisible(false);
    dispatch(returnToCommentRequestAction());              
  }, []);

  return (
    <article>      
      <Card      
        headStyle={BoardCardHeader}
        bodyStyle={BoardCardBody}
        hoverable              
        extra={[          
          <Popover            
            trigger="click"  
            content={
              <>
                <Button>Modify</Button>
                <PostDeleteModal post={post} />
              </>
            }             
          >
            <MoreIcon key="ellipsis"/>
          </Popover>
        ]}      
      > 
        <Row>
          <ColWrapper xs={24} md={16}>
            <CardTextWrapper>
              <CardText                
                title={<CardTitle>{post.title}</CardTitle>}
                description={post.desc}
                onClick={showPostModal}
              />
              <CardContent onClick={showPostModal}>{post.recipes}</CardContent>
            </CardTextWrapper>

            <div>
              {
                liked 
                ? <HeaderBtn type='text' icon={<TwoToneHeartBtnIcon twoToneColor="#eb2f96" onClick={unLikePost} />}>{post.Likers.length}</HeaderBtn>
                : <HeaderBtn type='text' icon={<HeartBtnIcon />} onClick={onLikePost}>{post.Likers.length}</HeaderBtn>
              }                               
              <HeaderBtn type='text' icon={<CommentBtnIcon />} onClick={boardCardCommentBtn} >{post.Comments.length}</HeaderBtn>            
            </div>
          </ColWrapper>
          
          <Col xs={24} md={8}>
            <CardImageWrapper>
              <ImageWrapper
                alt="board image"                
                src={`http://localhost:3065/${post.Images[0]?.src}`}
                onClick={showPostModal}
              />
            </CardImageWrapper>
          </Col>
        </Row>
      </Card>
        
      <Modal            
        centered
        visible={visible}
        onOk={boardmodalOkBtn}
        onCancel={boardmodalCancelBtn}
        width={1000}
      > 
        <PostModal post={post} />
      </Modal>        
    </article>
  );
};

BoardCard.propTypes = {
  post: PropTypes.shape({
    id: PropTypes.number,
    User: PropTypes.object,
    title: PropTypes.string,
    desc: PropTypes.string,
    content: PropTypes.arrayOf(PropTypes.object),
    Images: PropTypes.arrayOf(PropTypes.object),
    tag: PropTypes.string,
    Comments: PropTypes.arrayOf(PropTypes.object),
  })
};

export default BoardCard;

I tried to solve the problem, but couldn't find a way.

So, I would like to know why the above problem occurs and how to solve it.

CodePudding user response:

You must put the key on the first child

const BoardList = () => {
  const { boardPosts } = useSelector((state) => state.user);

  return (
    <section>
      <List  
          itemLayout="vertical"
          bordered    
          size="large"
          pagination={{
            onChange: (page) => console.log(page), pageSize: 3,
          }}
          dataSource={boardPosts}    
          renderItem={(item) => (  
            <List.Item key={item.id}>
              <BoardCard post={item}/>
            </List.Item>         
        )}
      />          
    </section>
  )
};
  • Related