0

I have an array of dictionaries. Each dict represents a row in the table that should be appearing on the UI. Each row should respect one of two conditions. Based on these conditions the background color of that row should be in one two options. My solution was to analyze the state and divide it into different arrays. Then I map the two arrays (one after the other) with different background colors. I didn't like this option because it is basically repeating the same code. It will also prohibit me from implementing an overall research functionality in a next step. Can anyone propose a map function that takes the overall state and return each row with respect to background color given to it?

 const TsdzList = (props) => {
    // all dicts to map
    const [testPackagesList, setTestPackagesList] = useState([]);

    // rows that respect cdt1
    const [newTestPackages, setNewTestPackages] = useState([]);

    // rows that respect cdt2
    const [oldTestPackages, setOldTestPackages] = useState([]);

    const getNewTestPackages = () => {
        let tsdzNewTestPackageNames = [];
        let tsdzOldTestPackageNames = [];
        for (const dict of testPackagesList) {
            if (condition1) {
                tsdzNewTestPackageNames.push(dict);
            }
            if (condition2) {
                tsdzOldTestPackageNames.push(dict);
            }
        }
        setNewTestPackages(tsdzNewTestPackageNames);
        setOldTestPackages(tsdzOldTestPackageNames);
    };
    return (
                                           
            <Table size="small">
              <TableHead>
                <TableRow>
                    <TableCell>ID</TableCell>
                    <TableCell>data</TableCell>
                </TableRow>
              </TableHead>
              <TableBody>
                  {newTestPackages.map((report, index) => (
                    <TableRow>
                      <TableCell required>{report.id}</TableCell>
                      <TableCell>{report.data}</TableCell>
                    </TableRow>
                   ))}
                  {oldTestPackages.map((report, index) => (
                     <TableRow key={index}>
                        <TableCell required>{report.id}</TableCell>
                        <TableCell>{report.data}</TableCell>    
                     </TableRow>
                  ))}
                    </TableBody>
                </Table>            
            <Button
              sx={{ m: 2 }}
              onClick={() => {
              getNewTestPackages();
              }}
            variant="contained"
            >
                Show
            </Button>
    );
};

From the code one can notice that the only difference between the two mapped functions is the background color. Is it possible to use only one map function that looks something like this {testPackagesList.map((report, index) => ( and get rid of that button Show? instead of that button, the analysis can be begin as soon as the testPackagesList is filled.

hous1956
  • 33
  • 3
  • 1
    That's a lot of code here, can you create a https://stackoverflow.com/help/minimal-reproducible-example which removes the unnecessary code? – Ruan Mendes Aug 11 '22 at 17:18
  • 1
    You can use filter to get the two arrays you need. `testPackagesList .filter(()=> condition1)` and `testPackagesList.filter(()=> condition2)` – Ruan Mendes Aug 11 '22 at 17:20
  • Minor nitpick: there's no such thing as a `dict` in JavaScript, they're referred to as "objects", or more colloquially as "maps." – Matt Morgan Aug 11 '22 at 17:20
  • @MattMorgan JavaScript has [Maps](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), an object is not a Map. – Ruan Mendes Aug 11 '22 at 17:21
  • Yes, JavaScript now has a formal `Map` class, I was speaking of a "map" in the more colloquial sense referred to here: https://stackoverflow.com/a/2884200/3084820 – Matt Morgan Aug 11 '22 at 17:26
  • @JuanMendes I removed the unnecessary code. I hope its ok – hous1956 Aug 12 '22 at 12:16
  • @MattMorgan You can colloquially refer to it as a dictionary too, then, since you just mean a key value store. Sorry, if you're going to nit-pick, pick something more relevant. – Ruan Mendes Aug 12 '22 at 13:55
  • @hous1956 You already have two solutions offered. One in my comments and another repeated in the two existing answers. – Ruan Mendes Aug 12 '22 at 13:57
  • Alternatively, you could sort your array making sure the new ones go first and add a property to each item indicating what background color they should be. – Ruan Mendes Aug 12 '22 at 14:07
  • It's also unclear whether some of the records should not be displayed, that is, whether some records don't meet either condition. – Ruan Mendes Aug 12 '22 at 14:28

2 Answers2

0

How about a ternary operator in sx that checks your condition and chooses the appropriate color?

sx={{ backgroundColor: condition1 ? "#e3f2fd" : "#ffffff" }}
Deepak
  • 2,660
  • 2
  • 8
  • 23
  • Or hopefully, just sets a semantic CSS classname to make it easy to modify the color. However, the OP's original solutions would first list the new packages and the then the old packages, your solution is keeping them in the original order. – Ruan Mendes Aug 12 '22 at 13:56
  • Another problem with this is that some rows may get filtered out with the OP's approach, whereas in this approach, all the rows would always display, regardless of whether both conditions were false. – Ruan Mendes Aug 12 '22 at 14:08
0

This solves your issue:

<TableBody>
    {testPackagesList.map((report, index) => (
        <TableRow key={report.id} style={{ backgroundColor: condition1 ? "green" : "red" }}>
            <TableCell required>{report.id}</TableCell>
            <TableCell>{report.data}</TableCell>
        </TableRow>
    ))}
</TableBody>
// no need for button now as data is processed right away
deaponn
  • 837
  • 2
  • 12