Search code examples
javascriptreactjsmaterial-uidatagrid

How to use two renderCell in datagrid from material ui and avoid double/same render


I use material ui to render my data in table form.

I have to use renderCell for two properties (level by user and level by referent)

problem: material ui shows me 'level by referent' twice because it replaces 'level by user' with 'level by referent'.

the tab with the two columns

    import React from 'react';
    import { useSelector } from 'react-redux';
    import { TableReusable } from '../../reusable/TableReusable';
    import { Box, CircularProgress, Typography } from '@mui/material';
    import useLevelToLetterConversion from '../../reusable/UseLevelConverter';
    
    const TcgTable = () => {
      const oneUserSkill = useSelector((state) => state.user?.oneUserSkill);
    
      const rows = oneUserSkill?.skills?.tcg;
      const convertedRows = useLevelToLetterConversion(rows);
    
      let columns =
        convertedRows?.length > 0
          ? [    {
            headerName: 'Level by user',
            headerAlign: 'center',
            align: 'center',
            renderCell: (convertedRows) => {
              const userLevel = convertedRows?.row?.Level?.find(
                (level) => level?.Role === 'User'
              );
              return (
                <Typography
                  sx={{
                    textAlign: 'center',
                    fontSize: '0.875rem',
                    width: 150,
                    height: 40,
    
                    ...(userLevel?.Level === 'Expert' && {
                      color: 'green',
                      fontWeight: 'bold',
                    }),
                    ...(userLevel?.Level === 'Confirmed' && {
                      color: 'green',
                    }),
                    ...(userLevel?.Level === 'Intermediate' && {
                      color: 'orange',
                    }),
                    ...(userLevel?.Level === 'Beginner' && {
                      color: 'lightsalmon',
                    }),
                    ...(userLevel?.Level === 'Unknow' && { color: 'grey' }),
                  }}
                >
                  {userLevel?.Level}
                </Typography>
              );
            },
          },
              {
                headerName: 'Level by referent',
                headerAlign: 'center',
                align: 'center',
                renderCell: (convertedRows) => {
                  const referentLevel = convertedRows?.row?.Level?.find(
                    (level) => level?.Role === 'Referent'
                  );
                  console.log('2', referentLevel);
    
                  return (
                    <Typography
                      sx={{
                        textAlign: 'center',
                        fontSize: '0.875rem',
                        width: 150,
                        height: 40,
    
                        ...(referentLevel?.Level === 'Expert' && {
                          color: 'green',
                          fontWeight: 'bold',
                        }),
                        ...(referentLevel?.Level === 'Confirmed' && {
                          color: 'green',
                        }),
                        ...(referentLevel?.Level === 'Intermediate' && {
                          color: 'orange',
                        }),
                        ...(referentLevel?.Level === 'Beginner' && {
                          color: 'lightsalmon',
                        }),
                        ...(referentLevel?.Level === 'Unknow' && { color: 'grey' }),
                      }}
                    >
                      {referentLevel?.Level}
                    </Typography>
                  );
                },
              },
            ].concat(
              Object.keys(convertedRows[0])
                .filter(
                  (field) =>
                    field !== 'updated_at' &&
                    field !== 'created_at' &&
                    field !== 'id' &&
                    field !== 'Level'
                )
                .map((field) => {
                  return {
                    field: field,
                    headerName: field,
                    flex: 1,
                  };
                })
            )
          : [];


  return <TableReusable data={convertedRows} columns={columns} bool={false} />;
};

My 'table reusable'

import React from 'react';
import {
  DataGrid,
  GridToolbar,
  GridToolbarQuickFilter,
} from '@mui/x-data-grid';
import { useDispatch } from 'react-redux';
import { Box, Stack } from '@mui/material';

export const TableReusable = ({ data, columns, bool, setSkillSelected }) => {
  const dispatch = useDispatch();
  const onRowsSelectionHandler = (ids) => {
    const selectedRowsData = ids?.map((id) =>
      data?.find((row) => row?._id === id || row?.id === id)
    );
    if (setSkillSelected) {
      dispatch(setSkillSelected(selectedRowsData));
    }
  };

  function NoRowsOverlay() {
    return (
      <Stack height="100%" alignItems="center" justifyContent="center">
        No skills for the moment
      </Stack>
    );
  }

  function NoResultsOverlay() {
    return (
      <Stack height="100%" alignItems="center" justifyContent="center">
        No results
      </Stack>
    );
  }

  function QuickSearchToolbar() {
    return (
      <Box
        sx={{
          display: 'flex',
          justifyContent: 'space-between',
          p: 0.5,
          pb: 0,
        }}
      >
        <GridToolbar />
        <GridToolbarQuickFilter
          quickFilterParser={(searchInput) =>
            searchInput
              .split(',')
              .map((value) => value.trim())
              .filter((value) => value !== '')
          }
        />
      </Box>
    );
  }

  return (
    <>
      <DataGrid
        density="comfortable"
        sx={{
          height: data?.length > 0 ? '100%' : 250,
          width: '100%',
          background: 'white',
          '.MuiDataGrid-columnHeaderTitle': {
            fontWeight: 'bold !important',
            overflow: 'visible !important',
          },
        }}
        rows={data}
        getRowId={(row) => row?.id || row?._id || row?.CommonId}
        columns={columns}
        initialState={{
          pagination: { paginationModel: { pageSize: 10 } },
          ...data.initialState,
        }}
        onRowSelectionModelChange={(ids) => onRowsSelectionHandler(ids)}
        components={{ NoRowsOverlay, NoResultsOverlay }}
        pageSizeOptions={[5, 10, 15, 20, 50, 100]}
        checkboxSelection={bool}
        slots={{ toolbar: QuickSearchToolbar }}
        componentsProps={{
          pagination: {
            labelRowsPerPage: 'Nb by page',
          },
        }}
      />
    </>
  );
};

What I have already tried:

If I switch the position in columns of 'level by user' and 'level by referent' then it is now 'level by user' which will be displayed twice

I also tried putting 'level by user' first and then adding 'level by referent' in the concat. But the same problem happens (I get the columns 'level by referent' twice)


Solution

  • I found an answer. Each column in the DataGrid should have a unique field property that identifies the column. In my code, the field property is not explicitly set for the 'Level by user' and 'Level by referent' columns, which might be causing the issue.

    I have now add 'field: 'levelByReferent' and the same for user and it's now working!

     {
                headerName: 'Level by user',
                headerAlign: 'center',
                align: 'center',
                field: 'levelByUser',
                renderCell: (convertedRows) => {
                  const userLevel = convertedRows?.row?.Level?.find(
                    (level) => level?.Role === 'User'
                  );
                  return (
                    <Typography
                      sx={{
                        textAlign: 'center',
                        fontSize: '0.875rem',
                        width: 150,
                        height: 40,
    
                        ...(userLevel?.Level === 'Expert' && {
                          color: 'green',
                          fontWeight: 'bold',
                        }),
                        ...(userLevel?.Level === 'Confirmed' && {
                          color: 'green',
                        }),
                        ...(userLevel?.Level === 'Intermediate' && {
                          color: 'orange',
                        }),
                        ...(userLevel?.Level === 'Beginner' && {
                          color: 'lightsalmon',
                        }),
                        ...(userLevel?.Level === 'Unknow' && { color: 'grey' }),
                      }}
                    >
                      {userLevel?.Level}
                    </Typography>
                  );
                },
              },
              {
                headerName: 'Level by referent',
                headerAlign: 'center',
                align: 'center',
                field: 'levelByReferent',
                renderCell: (convertedRows) => {
                  const referentLevel = convertedRows?.row?.Level?.find(
                    (level) => level?.Role === 'Referent'
                  );
                  console.log('2', referentLevel);
    
                  return (
                    <Typography
                      sx={{
                        textAlign: 'center',
                        fontSize: '0.875rem',
                        width: 150,
                        height: 40,
    
                        ...(referentLevel?.Level === 'Expert' && {
                          color: 'green',
                          fontWeight: 'bold',
                        }),
                        ...(referentLevel?.Level === 'Confirmed' && {
                          color: 'green',
                        }),
                        ...(referentLevel?.Level === 'Intermediate' && {
                          color: 'orange',
                        }),
                        ...(referentLevel?.Level === 'Beginner' && {
                          color: 'lightsalmon',
                        }),
                        ...(referentLevel?.Level === 'Unknow' && { color: 'grey' }),
                      }}
                    >
                      {referentLevel?.Level}
                    </Typography>
                  );
                },
              },