Reputation: 1298
I am creating normally table rows and columns when I am using the simple map function with the data shown below, that works just fine:
const tableRows = [
{
name: 'SickLeave difference',
januaryPayment: '-12000',
febrauaryPayment: '0',
},
{
name: 'Holiday difference',
januaryPayment: '10000',
febrauaryPayment: '25000',
},
{
name: 'Result',
januaryPayment: '0',
febrauaryPayment: '23000',
},
];
<Table headerTextCodes={headerTextCodes} allowFormattedHeader={false}>
{ tableRows.map(row => (
<TableRow>
<TableColumn>
{ row.name }
</TableColumn>
<TableColumn>
{ row.januaryPayment }
</TableColumn>
<TableColumn>
{ row.febrauaryPayment }
</TableColumn>
</TableRow>
))
}
</Table>
But, when I am trying to create table rows and columns where I am creating the data by first formatting the result that I am mocking currently as a backend response:
const result = {
periodFrom: '2018-05-01',
periodTo: '2018-07-31',
sumDifference: 17873,
periodsPerReceiver: [
{
receiverType: {
code: 'ARBG_PRIV',
name: null,
},
resultsPerMonth: [
{
from: '2018-05-01',
to: '2018-05-31',
resultPerField: [
{
fieldCode: {
code: 'SP',
name: null,
},
previouslyPayed: 0,
newAmount: 2662,
difference: 2662,
},
],
isNewPaymentPeriod: false,
},
{
from: '2018-06-01',
to: '2018-06-30',
resultPerField: [
{
fieldCode: {
code: 'FP',
name: null,
},
paid: 6899,
newAmount: 0,
difference: -6899,
},
],
isNewPaymentPeriod: false,
},
{
from: '2018-07-01',
to: '2018-07-31',
resultPerField: [
{
fieldCode: {
code: 'FP',
name: null,
},
paid: 0,
newAmount: 20012,
difference: 20012,
},
],
isNewPaymentPeriod: false,
},
],
},
{
receiverType: {
code: 'BRUKER',
name: null,
},
resultsPerMonth: [
{
from: '2018-05-01',
to: '2018-05-31',
resultPerField: [
{
fieldCode: {
code: 'FP',
name: null,
},
paid: 0,
newAmount: 0,
difference: 0,
},
],
isNewPaymentPeriod: false,
},
{
from: '2018-06-01',
to: '2018-06-30',
resultPerField: [
{
fieldCode: {
code: 'FP',
name: null,
},
paid: 0,
newAmount: 2098,
difference: 2098,
},
],
isNewPaymentPeriod: false,
},
{
from: '2018-07-01',
to: '2018-07-31',
resultPerField: [
{
fieldCode: {
code: 'FP',
name: null,
},
paid: 0,
newAmount: 0,
difference: 0,
},
],
isNewPaymentPeriod: false,
},
],
},
],
};
I have created this function to structure data in the way I could use it to create table and table rows later in the render function:
const resultPerReceiver = (receiver) => {
const receiverObject = {
receiver: receiver.receiverType,
fields: [],
};
receiver.resultsPerMonth.forEach((monthResult) => {
monthResult.resultPerFields.forEach((resultPerField) => {
const fieldExists = receiverObject.field.find(e => e.field.code === resultPerField.fieldCode.code);
if (fieldExists) {
fieldExists.rows.forEach((row) => {
const rowExists = row.resultPerMonth.find(e => e.from === monthResult.from);
if (!rowExists) {
const newAmount = {
from: monthResult.from,
to: monthResult.to,
amount: resultPerField.newAmount,
};
const paid = {
from: monthResult.from,
to: monthResult.to,
amount: resultPerField.paid,
};
const difference = {
from: monthResult.from,
to: monthResult.to,
amount: resultPerField.difference,
};
fieldExists.rows.find(e => e.name === 'newAmount').resultPerMonth.push(newAmount);
fieldExists.rows.find(e => e.name === 'paid').resultPerMonth.push(paid);
fieldExists.rows.find(e => e.name === 'difference').resultPerMonth.push(difference);
}
});
} else {
receiverObject.field.push({
field: resultPerField.fieldCode,
rows: [
{
name: 'newAmount',
resultPerMonth: [
{
from: monthResult.from,
to: monthResult.to,
amount: resultPerField.newAmount,
},
],
},
{
name: 'paid',
resultPerMonth: [
{
from: monthResult.from,
to: monthResult.to,
amount: resultPerField.paid,
},
],
},
{
name: 'difference',
resultPerMonth: [
{
from: monthResult.from,
to: monthResult.to,
amount: resultPerField.difference,
},
],
},
],
});
}
});
});
return receiverObject;
};
const formattedResult = result.periodsPerReceiver.map(receiver => resultPerReceiver(receiver));
This gives the result that looks something like this:
const formattedResult = [
{
receiver: {code: "ARBG_PRIV", name: null },
fields: [
{ field: { code: "SP", name: null },
rows: [
{name: "newAmount", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
},
{name: "paid", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
},
{name: "difference", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
}
]
},
{ field: { code: "FP", name: null },
rows: [
{name: "newAmount", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
},
{name: "paid", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
},
{name: "difference", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
}
]
},
]
},
{
receiver: {code: "BRUKER", name: null },
fields: [
{ field: { code: "SP", name: null },
rows: [
{name: "newAmount", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
},
{name: "paid", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
},
{name: "difference", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
}
]
},
{ field: { code: "FP", name: null },
rows: [
{name: "newAmount", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
},
{name: "paid", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
},
{name: "difference", resultPerMonth: [
{from: "2018-06-01", to: "2018-06-31", amount: 2662},
{from: "2018-07-01", to: "2018-07-31", amount: 2662}
]
}
]
},
]
},
]
Then, I am trying to render this result from the function like this in the render function:
<div className={styles.table}>
{
formattedResult.map(reciever => (
<Table>
{ reciever.fields.map(field => field.rows.map(row => (
<TableRow>
<TableColumn>
<Image
tabIndex="0"
className={styles.expandButton}
src={arrowDownImageUrl}
altCode="Timeline.openData"
/>
{ row.name }
</TableColumn>
{ row.resultPerMonth.map(month => (
<TableColumn>
{ month.amount }
</TableColumn>
))}
</TableRow>
)))}
</Table>
))}
</div>
But, when I try to do it like that, I get an error:
Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. in tbody (created by Table)
I have checked all the imports in the component, and I am importing them right, because this error is not happening when I am rendering the simple data shown above. I have no idea why is this happening in the latter case, what am I doing wrong?
Here you can see the sandbox for it.
Upvotes: 1
Views: 433
Reputation: 131
In your second case, you are using forEach
which returns undefined
.
You should use map
in order to get an array.
Be careful in your case, you will get an array of arrays. Maybe you should use flatMap
from lodash or the spread operator.
Upvotes: 3