yodellingbutters
yodellingbutters

Reputation: 345

How to read from JavaScript Objects when the property is dynamic?

I have a JavaScript Object which looks something like following:

{
"Finance": [
    {
        "id": 3,
        "first_name": "Test",
        "last_name": "Emp3",
        "email": "[email protected]",
        "department": "Finance",
        "phone": "17894561235",
        "job_title": "Manager",
        "display_name": ""
    }
],
"Account": [
    {
        "id": 4,
        "first_name": "Test",
        "last_name": "Emp4",
        "email": "[email protected]",
        "department": "Account",
        "phone": "14567891236",
        "job_title": "Manager",
        "display_name": ""
    }
],
"HR": [
    {
        "id": 5,
        "first_name": "Test",
        "last_name": "Emp5",
        "email": "[email protected]",
        "department": "HR",
        "phone": "17894556556",
        "job_title": "Manager",
        "display_name": ""
    }
]

} Getting the above data by following function call:

 const [Data, setData] = useState();
 const getdata = async () => {
    setLoading(true);
    let Data = [];
    try {
      let result = await getDATA(
        subscription,
        customer
      );
      let emp = result.data; 
      Data = emp;
      console.log(result.data);
      setData(Data);

    } catch (e) {
      setErrors(true);
      setStatus(
        <>
          <FormattedMessage id="GENERAL.ERROR" />
          <a
            
            target="_blank"
            rel="noopener noreferrer"
          >
            <FormattedMessage id="GENERAL.CONTACT_SUPPORT" />
          </a>
        </>
      );
    }
    setLoading(false);
  }

In the above JavaScript Object I have dynamic Department name which I have no idea what it can be.
My task is to make a Table something like this: enter image description here

Following is my render:

<Modal.Body>         
        {data ? data.map((e, key) => {
            return (
            <Accordion defaultActiveKey="0">
                <Card className="subscription-manager-expansion-card">
                  <Card.Header className="subscription-manager-expansion-header">
                    <Row>
                        <Col xs={12} sm={3} md={2} lg={1}>
                            <div className="rectangle-172">
                                <ContextAwareToggle  eventKey="0"></ContextAwareToggle>
                            </div>
                        </Col>
                        <Col xs={6} sm={6} md={8} lg={8}>
                            <span classname="subscription-manager-expansion-header-title"> {e} </span>
                        </Col>
                        <Col xs={6} sm={3} md={2} lg={1}>
                            <Form.Check type="checkbox" onChange={checkAddSubscriber} />
                        </Col>
                    </Row>
                  </Card.Header>
                  <Accordion.Collapse eventKey="0">
                    <Card.Body>
                                <div className="widget4" key={e}>
                                <Table>
                                    <thead>
                                        <th className="FinancialModel-title-substring"></th>
                                        <th className="FinancialModel-title-substring"></th>
                                    </thead>
                                    <tbody>
                                        {e ? e.map((es, key) => {
                                        return (
                                                <tr key={es.first_name}>
                                                    <td className="subscription-manager-modal-table-name">{es.first_name + " " + es.last_name} </td>
                                                    <td className="subscription-manager-modal-table"> {es.email}</td>
                                                    <td>
                                                        <Form.Check type="checkbox" checked={isChecked} />
                                                    </td>
                                                </tr>
                                            );
                                        }) : undefined}
                                    </tbody>
                                </Table>
                                </div>
                    </Card.Body>
                  </Accordion.Collapse>
                </Card>
            </Accordion>
            );
        }) : undefined}
        </Modal.Body>

Following is what I am having trouble with:

  1. But for some reason I am getting Uncaught TypeError: Data.map is not a function
  2. Also, how can I read and print the Department Name in the Header (e.g Finance, Account etc.) since it is not known beforehand and it could be any thing.

Please guide me through it.

Upvotes: 0

Views: 48

Answers (1)

Luke Storry
Luke Storry

Reputation: 6702

You are getting the error Data.map is not a function because on the first render, before you have set the data, Data is undefined.

Change the initialisation to to have a default value of an empty list:

const [data, setData] = useState([]);

As for your second question, you can use Object.entries(), which gives you an array of [key, value] pairs for your object. You can then map over those, like so:

Object.entries(data)
      .map(([departmentName, values]) =>{
       return (<div>
                 <h1>departmentName</h1>
                 <DepartmentComponent info={values} />
               </div>)
       })

Upvotes: 1

Related Questions