react-bootstrap-table2 icon indicating copy to clipboard operation
react-bootstrap-table2 copied to clipboard

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

Open jaballogian opened this issue 4 years ago • 2 comments

Question There is a warning Warning: Each child in a list should have a unique "key" prop for using custom PaginationListStandalone.

I know that it's only a warning but my team leader asks me to remove it. I don't find any map() function in my code. So I wonder, what's wrong with my code so the error appears?

Screenshots

Here is the screenshot of browser console: image

Here is the screenshot of my custom pagination: image

codesandbox

Table.js

import React, { useState } from 'react'

// BOOTSTRAP
import BootstrapTable from 'react-bootstrap-table-next'
import paginationFactory, {
    PaginationProvider,
    PaginationListStandalone,
    SizePerPageDropdownStandalone
} from 'react-bootstrap-table2-paginator'
import ToolkitProvider from 'react-bootstrap-table2-toolkit'

// STYLES
import './datatables.scss'
import './table.scss'

const Table = (props) => {

    const { tableData, columns, keyField } = props

    let initialStartAndEndPage = `1 - 10`
    if(tableData.length < 10) {
        initialStartAndEndPage = `1 - ${tableData.length}`
    }

    const [ startAndEndPage, setStartAndEndPage ] = useState(initialStartAndEndPage)
    const [ selectedSizePerPage, setSelectedSizePerPage ] = useState(10) 

    const CUSTOMWHITESMOKE = '#F9F3F4'
    const CUSTOMTOMATO = '#FF3C3C'

    const pageButtonRenderer = ({
        page,
        active,
        onPageChange
    }) => {
        const handleClick = (e) => {
            e.preventDefault()
            onPageChange(page)
        }

        const activeStyle = {}

        if (active) {
            activeStyle.backgroundColor = CUSTOMTOMATO
            activeStyle.color = 'white'
        } else {
            activeStyle.backgroundColor = 'white'
            activeStyle.color = 'black'
        }
        if (typeof page === 'string') {
            activeStyle.backgroundColor = CUSTOMWHITESMOKE
            activeStyle.color = CUSTOMTOMATO
        }

        return (
            <li className='page-item'>
                <div 
                    className='pagination-anchor' 
                    onClick={ handleClick } 
                    style={ activeStyle }
                >
                    { page }
                </div>
            </li>
        )
    }

    const paginationOptions = {
        pageButtonRenderer,
        sizePerPage: selectedSizePerPage,
        sizePerPageList: [ 10, 20, 50 ],
        totalSize: tableData.length,
        custom: true,
        firstPageText: '<<',
        prePageText: '<',
        nextPageText: '>',
        lastPageText: '>>',
        onSizePerPageChange: (sizePerPage, page) => {
            updateStartAndEndPage(page, sizePerPage)
        },
        onPageChange: (page, sizePerPage) => {
            updateStartAndEndPage(page, sizePerPage)
        }
    }

    const updateStartAndEndPage = (inputPage, inputSizePerPage) => {
        let endPage = inputSizePerPage * inputPage
        let startPage = endPage - inputSizePerPage + 1
        if(endPage > tableData.length) {
            endPage = tableData.length
        }
        setStartAndEndPage(`${startPage} - ${endPage}`)
        setSelectedSizePerPage(inputSizePerPage)
    }

    return (
        <React.Fragment>
            <PaginationProvider
                pagination={paginationFactory(paginationOptions)}
                keyField={keyField}
                columns={columns}
                data={tableData}
            >
                {({ paginationProps, paginationTableProps }) => (
                    <ToolkitProvider
                        keyField={keyField}
                        columns={columns}
                        data={tableData}
                        search
                    >
                        {toolkitProps => (
                            <React.Fragment>
                                {/* TABLE */}
                                <BootstrapTable
                                    keyField={keyField}
                                    responsive
                                    bordered={false}
                                    striped={false}
                                    classes={
                                        'table align-middle table-nowrap'
                                    }
                                    headerWrapperClasses={'thead-light'}
                                    {...toolkitProps.baseProps}
                                    {...paginationTableProps}
                                />

                                {/* PAGINATION AND SIZE PER PAGE */}
                                <div className='table-pagination-container'>
                                    {/* PAGINATION */}
                                    <PaginationListStandalone
                                        className='table-pagination'
                                        {...paginationProps}
                                    />

                                    {/* SIZE PER PAGE DROPDOWN */}
                                    <SizePerPageDropdownStandalone
                                        className='table-size-perpage'
                                        {...paginationProps}
                                    />

                                    {/* SIZE PER PAGE INFO */}
                                    <div className='table-size-perpage-info'>
                                        <p className='table-size-perpage-text'>
                                            Showing {startAndEndPage} of {tableData.length}
                                        </p>
                                    </div>
                                </div>

                            </React.Fragment>
                        )}
                    </ToolkitProvider>
                )}
            </PaginationProvider>
        </React.Fragment>
    )
}

export default Table

Device.js (the component that uses Table.js component):

import React, { useState, useEffect } from 'react'

// COMPONENTS
import Table from '../../components/Table/Table'

// UTILS
import { fetchAPI } from '../../utils/fetchAPI'

// STYLES
import './device.scss'

const Device = () => {
    const [ tableData, setTableData ] = useState(null)

    const columns = [
		{
			dataField: 'id',
			text: 'ID',
			sort: true,
		},
		{
			dataField: 'name',
			text: 'Name',
			sort: true,
		},
		... // some objects here
	]

    const getData = async () => {
        const data = await fetchAPI()
        setTableData(data)
    }

    useEffect(() => {
        getData()
    }, []) // eslint-disable-line react-hooks/exhaustive-deps

    return (
        <div className='device-root'>
            {
                tableData && 
                <Table 
                    tableData={tableData} 
                    columns={columns}
                    keyField={'id'}
                />
            }
        </div>
    )
}

export default Device

jaballogian avatar Aug 09 '21 08:08 jaballogian

Did you find the solution?

fahad39 avatar Oct 24 '22 10:10 fahad39

Ok so i removed the warning. You have to pass a key prop to the li tag in the page button render method. There is one more prop of "title" pass to the page button render method you can set key to title

fahad39 avatar Oct 24 '22 10:10 fahad39