Sergio Rodriguez
Sergio Rodriguez

Reputation: 8688

Appending to object using react State

I've been stuck on this problem for a few hours, and I do not see how to resolve it.
I use material-UI tables to display data. The current setup populates dropdown options, from where the user can select a combination.

That selection is set into state, and it is displayed on the table. The problem arises when I make a second selection, where instead of appending the data, it overwrites the old data.

The final result should be a list of options. Not just the latest submission.

Lastly, I am passing only one arg for testing purposes; in production will have four args.

Any help is appreciated.

**main Page**
 const [dropdownState, setDropdownState] = useState({
        GridLOE: "",
        GridSelect: "",
    });


const handleDropdown = (event) => {
        setDropdownState({
            ...dropdownState,
            [event.target.name]: event.target.value,
        });
    };

    const gridLineOfEffortData = [
        "Crisis",
        "Activities",
        "Conflicts",
        "Networks",
        "Prioritization",
    ]

    const gridLineOfEffortOptionsData = [
        "Minimal",
        "Enhancing",
        "Critical",
    ]

    // DATA GRID
    const [dataGrid, setDataGrid] = useState({
        data: []
    })

    function createData(loeName, minimal, enhancing, critical) {
        return { loeName, minimal, enhancing, critical }
    }

    const handleGrid = () => {
        setDataGrid({
            ...dataGrid,
            data: [
                createData(dropdownState.GridLOE)
            ]
        })
        console.log(dropdownState.GridLOE)
    };

main page select dropdown and submit

<Grid container spacing={5} padding={3}>
   <Grid item lg={12} sm={12} xs={12}>
      <TableGridPrioritization
        rows={dataGrid.data}></TableGridPrioritization>
   </Grid>
   <Grid item lg={4} sm={6} xs={12}>
         <FieldDropdown
            selectId={"GridLOE"}
            selectTitle={"Select LOE"}
            selectValue={dropdownState.GridLOE}
            selectList={gridLineOfEffortData}
            handleChange={handleDropdown}
          >
         </FieldDropdown>
   </Grid>
   <Grid item lg={4} sm={6} xs={12}>
          <FieldDropdown
            selectId={"GridSelect"}
            selectTitle={"Minimal, enhancing, or critical"}
            selectValue={dropdownState.GridSelect}
            selectList={gridLineOfEffortOptionsData}
            handleChange={handleDropdown}
          >
          </FieldDropdown>
   </Grid>
   <Grid item lg={4} sm={6} xs={12}>
     <Button variant="contained" color="secondary" size="large" onClick={handleGrid}>ADD TO GRID</Button>
  </Grid>

imported component

// BASIC 
import React from "react";
import { withStyles } from "@material-ui/core/styles";
import styles from "../../components/RoutingTool/Theme";
// NEEDS REMOVING
import { makeStyles } from '@material-ui/core/styles';
// ELEMENTS 
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableContainer from '@material-ui/core/TableContainer';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Paper from '@material-ui/core/Paper';

const StyledTableCell = withStyles((theme) => ({
  head: {
    backgroundColor: theme.palette.common.black,
    color: theme.palette.common.white,
  },
  body: {
    fontSize: 14,
  },
}))(TableCell);

const StyledTableRow = withStyles((theme) => ({
  root: {
    '&:nth-of-type(odd)': {
      backgroundColor: theme.palette.action.hover,
    },
  },
}))(TableRow);

const useStyles = makeStyles({
  table: {
    minWidth: 700,
  },
});

export const TableGridPrioritization = props => {
  const classes = useStyles();

  return (
    <TableContainer component={Paper} className={props.classes.tablePrioritizationDataGrid}>
      <Table className={classes.table} aria-label="customized table">
        <TableHead>
          <TableRow>
            <StyledTableCell>Line of Effort</StyledTableCell>
            <StyledTableCell align="right">Minimal</StyledTableCell>
            <StyledTableCell align="right">Enhancing</StyledTableCell>
            <StyledTableCell align="right">Critical</StyledTableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {props.rows.map((row) => (
            <StyledTableRow key={row.loeName}>  
              <StyledTableCell component="th" scope="row">
                {row.loeName}
              </StyledTableCell>
              <StyledTableCell align="right">{row.minimal}</StyledTableCell>
              <StyledTableCell align="right">{row.enhancing}</StyledTableCell>
              <StyledTableCell align="right">{row.critical}</StyledTableCell>
            </StyledTableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}

Upvotes: 0

Views: 41

Answers (1)

Sean
Sean

Reputation: 975

As your dataGrid is an object with data in it you need to get all the current data instead of the current dataGrid but doing data:[...data, NEWDATA]. The below code should work.

// DATA GRID
const [dataGrid, setDataGrid] = useState({
    data: []
})

const handleGrid = () => {
    setDataGrid({
        data: [...dataGrid.data,
            createData(dropdownState.GridLOE)
        ]
    })
    console.log(dropdownState.GridLOE)
};

Upvotes: 1

Related Questions