2

I have API that returns some tabular data. I need to display these data in a Table. It's not clear to me how to achieve this goal.

Let's assume that I want to display the fields id and name stored in groups. How can I show them in the Material-UI Table?

Please see my current code below. It does not throw any error. But neither is shows a Table with the data.

import '../../App.css';
import React, { useEffect } from 'react'
import { makeStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
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';
import axios from 'axios'
import config from '../../config/config.json';

const useStyles = makeStyles((theme) => ({
    root: {
        width: '100%',
    },
    heading: {
        fontSize: theme.typography.pxToRem(18),
        fontWeight: theme.typography.fontWeightBold,
    },
    content: {
        fontSize: theme.typography.pxToRem(14),
        fontWeight: theme.typography.fontWeightRegular,
        textAlign: "left",
        marginTop: theme.spacing.unit*3,
        marginLeft: theme.spacing.unit*3,
        marginRight: theme.spacing.unit*3
    },
    table: {
        minWidth: 650,
    },
    tableheader: {
        fontWeight: theme.typography.fontWeightBold,
        color: "#ffffff",
        background: "#3f51b5"
    },
    tableCell: {
        background: "#f50057"
    },
    button: {
        fontSize: "12px",
        minWidth: 100
    },
}));


export function Main() {

    const [groups, setGroup] = React.useState('');

    const classes = useStyles();

    const options = {
        'headers': {
            'Authorization': `Bearer ${localStorage.getItem('accessToken')}`
        }
    }

    useEffect(() => {
        axios.get(config.api.url + '/api/test', options)
            .then( (groups) => {
                this.setState({response: groups})
            })
            .catch( (error) => {
                console.log(error);
            })
    }, [])

    return (
        <div className={classes.root}>

            <Grid container spacing={3}>
                <Grid item xs={12} className={classes.content}>
                    <TableContainer component={Paper}>
                        <Table id="split_table" size="small">
                            <TableHead>
                            </TableHead>
                            <TableBody>
                                {Object.keys(groups).map( (row, index) => (
                                    <TableRow key={index} selected="false">
                                        <TableCell>Test</TableCell>
                                        <TableCell>Test</TableCell>
                                    </TableRow>))}
                            </TableBody>
                        </Table>
                    </TableContainer>

                </Grid>    
            </Grid>
        </div>
    )
} 

Update:

As I mentioned in comments, I followed the recommendations from answers, but I still see an empty table, while I can see a correct value in console.

useEffect(() => {
        axios.get(config.api.url + '/api/test', options)
            .then( (groups) => {
                setGroup(groups.data.subtask)
                console.log(groups.data.subtask);
            })
            .catch( (error) => {
                console.log(error);
            })
    }, [])

    return (
        <div className={classes.root}>

            <Grid container spacing={3}>
                <Grid item xs={12} className={classes.content}>
                    <TableContainer component={Paper}>
                        <Table id="split_table" size="small">
                            <TableHead>
                            </TableHead>
                            <TableBody>
                                    {Object.keys(groups).map( (item, index) => (
                                    <TableRow key={index} selected="false">
                                        <TableCell>{item.user_id}</TableCell>
                                        <TableCell>{item.task_name}</TableCell>
                                    </TableRow>))}
                            </TableBody>
                        </Table>
                    </TableContainer>

                </Grid>    
            </Grid>
        </div>
    )

This is what I see in the browser:

enter image description here

This is an example of data (groups.data.subtask):

enter image description here

8
  • Use setGroup(groups) instead of this.setState({response: groups}) Commented Aug 5, 2020 at 15:15
  • I think a problem is here setGroup(groups.data.subtask[0]). Try to write it so setGroup(groups.data.subtask) Commented Aug 5, 2020 at 15:46
  • @AlexAV-dev: I tried it. It does not work. Commented Aug 5, 2020 at 15:48
  • @AlexAV-dev: Please see my last update where I posted an example of groups.data.subtask as you requested. Commented Aug 5, 2020 at 15:50
  • I updated my answer, check it out. The problem was that you gave us the wrong keys of objects Commented Aug 5, 2020 at 15:53

3 Answers 3

2

I think the problem is that you use this.setState instead of setGroup

useEffect(() => {
    axios.get(config.api.url + '/api/test', options)
        .then( (groups) => {
            setGroup(groups)
        })
        .catch( (error) => {
            console.log(error);
        })
}, [])

Change your map function

{Object.keys(groups).map( (row, index) => (
  <TableRow key={index} selected="false">
    <TableCell>{row._id}</TableCell>
    <TableCell>{row.user_id}</TableCell>
  </TableRow>))}

import '../../App.css';
import React, { useEffect } from 'react'
import { makeStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
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';
import axios from 'axios'
import config from '../../config/config.json';

const useStyles = makeStyles((theme) => ({
    root: {
        width: '100%',
    },
    heading: {
        fontSize: theme.typography.pxToRem(18),
        fontWeight: theme.typography.fontWeightBold,
    },
    content: {
        fontSize: theme.typography.pxToRem(14),
        fontWeight: theme.typography.fontWeightRegular,
        textAlign: "left",
        marginTop: theme.spacing.unit*3,
        marginLeft: theme.spacing.unit*3,
        marginRight: theme.spacing.unit*3
    },
    table: {
        minWidth: 650,
    },
    tableheader: {
        fontWeight: theme.typography.fontWeightBold,
        color: "#ffffff",
        background: "#3f51b5"
    },
    tableCell: {
        background: "#f50057"
    },
    button: {
        fontSize: "12px",
        minWidth: 100
    },
}));


export function Main() {

    const [groups, setGroup] = React.useState([]);

    const classes = useStyles();

    const options = {
        'headers': {
            'Authorization': `Bearer ${localStorage.getItem('accessToken')}`
        }
    }

useEffect(() => {
        axios.get(config.api.url + '/api/test', options)
            .then( (groups) => {
                setGroup(groups.data.subtask)
                console.log(groups.data.subtask);
            })
            .catch( (error) => {
                console.log(error);
            })
    }, [])

return (
    <div className={classes.root}>

        <Grid container spacing={3}>
            <Grid item xs={12} className={classes.content}>
                <TableContainer component={Paper}>
                    <Table id="split_table" size="small">
                        <TableHead>
                        </TableHead>
                        <TableBody>
                                {Object.keys(groups).map( (item, index) => (
                                <TableRow key={index} selected="false">
                                    <TableCell>{item.user_id}</TableCell>
                                    <TableCell>{item.task_name}</TableCell>
                                </TableRow>))}
                        </TableBody>
                    </Table>
                </TableContainer>

            </Grid>    
        </Grid>
    </div>
)
Sign up to request clarification or add additional context in comments.

8 Comments

not only using setState, he is using this.setState({response: groups}) (setting response state, not groups state).
@yaya I think it is not a problem because we anyway save response in state group. I can be wrong if it is so, please explain me why i'm do not right :)
doesn't this.setState({response: groups}) sets the value of groups variable to response state?
Thanks. Now I can see the table. But the content of this table is still wrong because I think that my code inside <Table>...</Table> is wrong. I see Test in all cells of the Table instead of a real data.
@Fluxy yeah you should replace <TableCell>Test</TableCell> with <TableCell>{row.yourcolname}</TableCell>
|
1

I think it's the Object.keys(groups) .

It's not React state, so it will not re-render?

Can you try to make a groupKey state and then useEffect to update the state when groups is updated.

const [groupKey,setGroupKey] = useState([]);

useEffect(() => {
  setGroupKey(Object.keys(groups));
},[groups]);

In the component , use

{groupKey.map((item, index) => (
  <TableRow key={index} selected="false">
    <TableCell>{item.user_id}</TableCell>
    <TableCell>{item.task_name}</TableCell>
  </TableRow>))
}

You get the idea.

7 Comments

can you please elaborate your answer? what do you mean by "groupKey state"? any example would be appreciated. thanks.
react will render only if it's state is changed. Object.keys() will give out a new array which is not a react state. so it will not re-render? just a suggestion.
I think you are right. But I don't understand some aspects of your example. What is [groups]?
@Fluxy it's the dependencies of useEffect. useEffect will accept two parameter.. a function to do side effect and an array of dependencies.. when the dependencies change, the function is executed again.
You need to replace initial value string with array [groupKey,setGroupKey] = useState([]);
|
1

Something like below should help: enter image description here

1 Comment

I get the error TypeError: groups.map is not a function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.