In a full stack application, I wrote a backend that returns JSON. The JSON Structure is similar to:
{
"2022-03-04T09:56:33.525Z": [
"https://amazon-s3-bucket-presigned-key-for-audio-data",
"https://amazon-s3-bucket-presigned-key-for-animation-data"
],
"2022-03-04T10:05:01.909Z": [
"https://amazon-s3-bucket-presigned-key-for-audio-data",
"https://amazon-s3-bucket-presigned-key-for-animation-data"
],
{...}
}
There’s x amount of audio sources, which will each have y amount of recordings collected from that source. Each recording from a given audio source is guaranteed to be unique to a timestamp, and will always have matching animation data. I have verified this to be the case, and the backend output is definitely not the problem here.
In the React.js frontend, I render a list of accordion components from inside an accordianList component. Each accordion element will have the name of the audio source that it’s been collected from, and a conditionally displayed dropdown chevron, dependent on whether or not recordings collected from that source exist. When the dropdown chevron is clicked, a list of custom audio players is rendered, each specific to an individual recording entry collected from that source.
AccordianList > Accordian * x > AudioEntry * y
The issue
I had this system working, but made some drastic changes to the data transfer format. I previously transmitted everything in one go- all recordings from all sources. This was quite large, and caused some issues.
Now, after these changes, when I render the AudioEntry
component the data inside the list does not render. The animation to change the dropdown chevron switches, as too does the dropdown state… However, the AudioEntry
component does not get rendered at all. I know this for a fact, as when I replace everything inside that element with a <li>
or <h1>
tag, it is not displayed. I have console logged the data received, and can confirm it exists and is in the right format.
I tried these two methods for iterating the JSON object:-
<div className={classes.accordian_content} aria-expanded={!thisSensorSelected}>
<ul>
{ Object.entries(dataList).map(([k, v])=> {
{console.log({k, v})}
<AudioEntry
key={k}
date={new Date(k).toLocaleString('gb')}
audioFile={v[0]}
animFile={v[1]}
dropdownClicked={thisSensorSelected}
filePlaying={filePlaying}
setFilePlaying={setFilePlaying}
/>
})}
</ul>
</div>
Where the console.log outputs exactly what is expected, but the list is not rendered. There are no errors in the developer tools.
The other method I tried was this:
{Object.keys(dataList).map(timestamp => {
<AudioEntry
key={timestamp}
date={new Date(timestamp).toLocaleString('en-gb')}
audioFile={dataList[timestamp][0]}
animFile={dataList[timestamp][1]}
dropdownClicked={thisSensorSelected}
filePlaying={filePlaying}
setFilePlaying={setFilePlaying}
/>
})}
Again, console.log displays exactly what I expected- but the element is not rendered (which is just a <li>
at this point).
For sake of clarity, I retrieve the data using an Axios wrapper, called inside an async useEffect function.
Things I have tried:
- Checking whether the
dataList
is empty first (using ternary) - Object.values
- Placing the Object.values/Object.keys/Object.entries inside of a fragment.
- Placing the entire
<ul>
inside a fragment - Changing the
thisSensorSelected
state prop to not include!
- Banging my head off of the keyboard