Reactjs, Table Cell With Different Background Color

react-table -- how to set background color for column headers only

check this code here

https://codesandbox.io/s/silent-fog-yprqd4?file=/src/App.js

th {
background-color: red;
}

the th tag is styled with a style variable

ReactJS 7 - How to conditionally change the background color of table cell only (not the row) based on its value?

The docs say you can set conditional styles like this: https://www.npmjs.com/package/react-data-table-component#conditional-style-object

const conditionalRowStyles = [
{
when: row => row.calories < 300,
style: {
backgroundColor: 'green',
color: 'white',
'&:hover': {
cursor: 'pointer',
},
},
},
// You can also pass a callback to style for additional customization
{
when: row => row.calories < 300,
style: row => ({
backgroundColor: row.isSpecia ? 'pink' : 'inerit',
}),
},
];

const MyTable = () => (
<DataTable
title="Desserts"
columns={columns}
data={data}
conditionalRowStyles={conditionalRowStyles}
/>
);

I quickly put together an example usings cell and styled components:

https://codesandbox.io/s/upbeat-galileo-r7p34?file=/src/App.js

import "./styles.css";
import DataTable from "react-data-table-component";
import styled from "styled-components";

const StyledCell = styled.div`
&.low {
background: green !important;
}
&.medium {
background: orange;
}
&.high {
background: red !important;
}
`;

export default function App() {
let items = [
{
Country: "Canada",
AdditionalNewCases: 500
},
{
Country: "England",
AdditionalNewCases: 5000
},
{
Country: "USA",
AdditionalNewCases: 500000
}
];
function getCssClass(value) {
if (value > 5000) return "high";
else if (value > 500) return "medium";
return "low";
}
return (
<DataTable
title="Covid-19 Stats"
defaultSortAsc="false"
responsive
defaultSortAsc={false}
striped
highlightOnHover
data={items}
columns={[
{
name: "number",
selector: (row, index) => index + 1,
disableSortBy: true
},
{
name: "Country",
selector: "Country",
sortable: true
},
{
name: "New Cases",
selector: "AdditionalNewCases",
sortable: true,
cell: (row) => (
<StyledCell className={getCssClass(row.AdditionalNewCases)}>
{row.AdditionalNewCases}
</StyledCell>
)
}
]}
/>
);
}

React: How to change Table cell background depending on cell value in React table

Just use a ternary operator and pass a class or value in

<td key="Questions" className={value > 0.25 ? 'greenclass' : 'redclass' }>

or

<td key="Questions" styles={{ background: value > 0.25 ? 'green' : 'red' }}>

Update for 3+ classes

I would use an outside function where you have an if/else or switch statement return className

Have this function outside the render

resolveClass = (value) => {
let className = ''

switch (true) {
case (value > 0.25):
className = 'green'
break;
case (value < 0):
className = 'red'
break;
default:
break
}

return className
}

Then inside the render <td key="Questions" className={resolveClass(paa.Questions)}>

Update cell background color when deleting the row. (react-table)

The main cause of this issue is keys. To learn more about how to use keys, you can check out React's official documentation here: https://reactjs.org/docs/lists-and-keys.html#keys

The main cause of this inconsistency is the code here

<tbody {...getTableBodyProps()}>
{page.map((row, i) => {
prepareRow(row)
return (
<ClickAndHold id={i} elmType={'tr'} onHold={e => openContextMenu(e, row)} {...row.getRowProps()} onContextMenu={e => openContextMenu(e, row)}>
{row.cells.map(cell => {
return <td {...cell.getCellProps([getCellProps(cell)])}>{cell.render('Cell')}</td>
})}
</ClickAndHold>
)
})}
</tbody>

The ClickAndHold component is passed the props from row.getRowProps(). row.getRowProps() returns an object that contains a key that looks something like row_0. Now, this key is dependent upon the row's position in the table. Suppose there were five rows, then their keys would be row_0, row_1, row_2, row_3, and row_4. If you deleted the 4th row (with key row_3), the fifth row (with key row_4) would get the fourth row's key. Suppose that you actually deleted the fourth row, then the keys would look like this: row_0, row_1, row_2, row_3. So, now, the fifth row (which previously had key row_4, but now has key row_3), has fourth row's key. Thus, when react re renders your tree, it'll pass the fourth row's props to fifth row. This means that if the fourth row had blue background, then fifth row will also have blue background. I know this is a handful, but I hope I'm making sense here.

To get around this issue, you need to pass a unique key to the row. This unique key should ideally come from the data that you're rendering. If I look at your data, you have an id that is unique. So, use this id as a key for ClickAndHold component. Summarizing everything, to resolve this issue, you need to edit the code as

<tbody {...getTableBodyProps()}>
{page.map((row, i) => {
prepareRow(row)
return (
<ClickAndHold id={i} elmType={'tr'} onHold={e => openContextMenu(e, row)} {...row.getRowProps()} key={row.original.id} onContextMenu={e => openContextMenu(e, row)}>
{row.cells.map(cell => {
return <td {...cell.getCellProps([getCellProps(cell)])}>{cell.render('Cell')}</td>
})}
</ClickAndHold>
)
})}

The row object inside the page list contains an original object that contains your data. So, you simply need to use id from your custom data, and use it as key. You need to pass key after {...row.getRowProps()} to override the key returned by row.getRowProps().

I've tested this in your codesandbox, and over there you simply need to edit the tr component found in line 85 inside CustomTable.jsx in this way.

<tr
id={i}
{...row.getRowProps()}
key={row.original.id}
onContextMenu={(e) => openContextMenu(e, row)}
>

I hope that's helpful.

Another suggestion, in your code for adding new row, you're chaning all the ids that come after the newly added row. This is code for reference.

setTableData((sequence) => {
const newData = sequence.reduce((acc, step) => {
if (incrementId) {
step.id = step.id + 1;
acc.push(step);
} else {
acc.push(step);
}
if (step.id === nextToId) {
newStep.id = newStep.id + 1;
acc.push(newStep);
incrementId = true;
}

return acc;
}, []);
return newData;
});

This will cause inconsistency because when you change id which is used as key for a row, on next re render, react will pass props to the newly added row that belonged to the previous row that the newly added row replaced. To learn more about this, check out this article: https://robinpokorny.medium.com/index-as-a-key-is-an-anti-pattern-e0349aece318. What I'm trying to say is, keys should be unique for every component inside the list, and if a component is added or deleted, any other component cannot take its key. You can use uuid for generating unique keys. Take a look here for how to use uuid https://www.npmjs.com/package/uuid.

Essentially, you need to be careful with dealing with keys, otherwise you risk severely degrading the performance of your application, or messing up the state of your component tree.

UPDATE

Sorry, but I was wrong about the root cause of this issue. Though it's true that there's a problem with the way you're using keys, the background color issue is not solely due to it. In fact, what causes background color to not change is because you set background-color: none. background-color doesn't have a property called none. So, this is an invalid CSS property, and it doesn't get updated in the DOM. This causes previously valid background-color to linger around, thus causing the issue. To fix this, you probably want to set background-color: unset or background-color: white when you want to remove the blue background. Hope that helps!

How to color specific cells in Table

You can use something like

<tr style={{'background-color': result.color}}>...</tr>

or

<tr style={{'background-color': shouldHighlight[key] ? 'red' : 'white'}}>...</tr>

Obviously in second case you need to findout before function, which table rows should be highlighted and store it in the array.

Also, you need to write your map function in format (result, key) => ... or you need to know id of the result.



Related Topics



Leave a reply



Submit