0

I am an absolute beginner on React.js. I check similar questions and apply some of them, still, I could not solve the problem. I added the .js file below. I use Django REST API to get data from my SQLite and try to put my data into a table. GET request gives me a JSON file and I try to convert it to a suitable data format.

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {makeStyles} from '@material-ui/core/styles';
import Box from '@material-ui/core/Box';
import Collapse from '@material-ui/core/Collapse';
import IconButton from '@material-ui/core/IconButton';
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 Typography from '@material-ui/core/Typography';
import Paper from '@material-ui/core/Paper';
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';

const useRowStyles = makeStyles({
  root: {
    '& > *': {
      borderBottom: 'unset',
    },
  },
});

function createData(name, mail, mss) {
  return {
    name,
    mail,
    history: [
      { massage: mss},
    ],
  };
}

function Row(props) {
  const { row } = props;
  const [open, setOpen] = React.useState(false);
  const classes = useRowStyles();

  return (
    <React.Fragment>
      <TableRow className={classes.root}>
        <TableCell>
          <IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)}>
            {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
          </IconButton>
        </TableCell>
        <TableCell component="th" scope="row">
          {row.name}
        </TableCell>
        <TableCell align="right">{row.mail}</TableCell>
      </TableRow>
      <TableRow>
        <TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
          <Collapse in={open} timeout="auto" unmountOnExit>
            <Box margin={1}>
              <Typography variant="h6" gutterBottom component="div">
                History
              </Typography>
              <Table size="small" aria-label="purchases">
                <TableHead>
                  <TableRow>
                    <TableCell>İçerik</TableCell>

                  </TableRow>
                </TableHead>
                <TableBody>
                  {row.history.map((historyRow) => (
                    <TableRow key={historyRow.massage}>
                      <TableCell component="th" scope="row">
                        {historyRow.massage}
                      </TableCell>

                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </Box>
          </Collapse>
        </TableCell>
      </TableRow>
    </React.Fragment>
  );
}

Row.propTypes = {
  row: PropTypes.shape({
    name: PropTypes.string.isRequired,
    mail: PropTypes.string.isRequired,
    history: PropTypes.arrayOf(
      PropTypes.shape({
        message: PropTypes.string.isRequired,
      }),
    ).isRequired,
  }).isRequired,
};


function CollapsibleTable(rows) {
  return (
    <TableContainer component={Paper}>
      <Table aria-label="collapsible table">
        <TableHead>
          <TableRow>
            <TableCell />
            <TableCell>Name</TableCell>
            <TableCell align="right">Mail</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {rows.map((row) => (
            <Row key={row.name} row={row} />
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}

const rows = [
  createData('Frozen yoghurt', "metegenez", "selam"),
  createData('Ice cream sandwich', "metegenez", "selam"),
  createData('Eclair', "metegenez", "selam"),
  createData('Cupcake', "metegenez", "selam"),
  createData('Gingerbread', "metegenez", "selam")];

function mapDatasInto() {
    return (
        this.state.data.map(contact => {
          return (
              createData(contact)
          );
        })
    );
  }

class Tablee extends Component {

  constructor(props) {
    super(props);
    this.state = {
      data: [],
      loaded: false,
      placeholder: "Loading"
    };
    this.componentDidMount = this.componentDidMount.bind(this);
    this.mapDatasInto = this.mapDatasInto.bind(this);
  }


  componentDidMount() {
    fetch("api/lead")
        .then(response => {
          if (response.status > 400) {
            return this.setState(() => {
              return {placeholder: "Something went wrong!"};
            });
          }
          console.log(response);
          return response.json();
        })
        .then(data => {
          this.setState(() => {
            return {
              data,
              loaded: true
            };
          });
        });


  }
  mapDatasInto() {
    return (
        this.state.data.map(contact => {
          return (
              createData(contact)
          );
        })
    );
  }

  render() {
    return (CollapsibleTable(mapDatasInto()));
  }
}
export default Tablee;

I used rows for debugging, but when I use the data in the state, I get an error like this. I believe there is a simple explanation for this.

Uncaught TypeError: Cannot read property 'state' of undefined
    at mapDatasInto (Table.js:181)
    at Tablee.render (Table.js:242)
    at finishClassComponent (react-dom.development.js:17160)
    at updateClassComponent (react-dom.development.js:17110)
    at beginWork (react-dom.development.js:18620)
    at HTMLUnknownElement.callCallback (react-dom.development.js:188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
    at invokeGuardedCallback (react-dom.development.js:292)
    at beginWork$1 (react-dom.development.js:23203)
    at performUnitOfWork (react-dom.development.js:22157)
  • 1
    Because you are calling `mapDatasInto()` here: `CollapibleTable(mapDatasInto())`. This is the function you defined outside your class and since it is not called as part of your class instance it doesn't have the correct `this` reference. You probably meant to use `this.mapDatasInto()` as that is called from your instance and would have the correct `this` reference – Patrick Evans Jun 28 '20 at 00:58
  • It solved my problem, thank you. Also, I did not realize that things I tried was not valid due to "Cache" in Chrome. You can disable it from ' https://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development'. – Mete Yıldırım Jun 28 '20 at 20:52

1 Answers1

0

I think fetch('api/lead') in componentDidMount doesn't return the data that you're looking for. Could you try console.data in componentDidMount, just to see if data is loaded? If data is there, means something wrong with the setState

Arif Oyong
  • 239
  • 2
  • 10