Reputation: 806
I'm creating a component with a view that can be opened and closed like an accordion. The data for the view comes from this JSON file:
{
"tracks": [
{
"uid": "001",
"line_number": "S123456",
"feed": [
{
"line_number": "S123456",
"outer_situation": "low",
"departure_time": "2020-04-21T10:55Z"
},
{
"line_number": "S123456",
"outer_situation": "high",
"departure_time": "2020-04-21T10:55Z"
},
{
"line_number": "S123456",
"departure_time": "2020-04-21T10:55Z"
}
]
},
{
"uid": "002",
"line_number": "S00000",
"feed": [
{
"line_number": "S123456",
"outer_situation": "low",
"departure_time": "2020-04-21T10:55Z"
},
{
"line_number": "S123456",
"outer_situation": "high",
"departure_time": "2020-04-21T10:55Z"
},
{
"line_number": "S123456",
"outer_situation": "high",
"departure_time": "2020-04-21T10:55Z"
}
]
}
]
}
Each "track" represents a row, so there could be unlimited numbers of rows. When my row is closed, it the map looks like this:
<div>
{connex.map((tracks) => (
<div
className={style.connection_container}
onClick={() => setShowConnections(!showConnections)}
onKeyPress={() => setShowConnections(!showConnections)}
role="button"
tabIndex="0"
>
<div span={1}>
</div>
<div span={3}>
<div className={style.vehicle_id}>
<p>{tracks.line_number}</p>
</div>
</div>
<div span={6}>
<span className={style.location_text}>
{tracks.origin}
</span>
<span> - </span>
<span className={style.location_text}>
{tracks.destination}
</span>
</div>
<div span={8}>
<div className={style.stop_point}>
<p>{tracks.stop_point}</p>
</div>
</div>
<div span={6}>
<span className={style.stop_point}>
<p>{tracks.arrival_time}</p>
</span>
</div>
</div>
))}
</div>
Before adding mapped JSON data, I was using with the information that would be included after I created the JSON, so the original toggle function works fine. However, now as I am trying to add a .map function inside of the opened view, I am doing something wrong in the syntax and I cannot figure out what it is.
https://stackblitz.com/edit/react-lnpfvu
error: JSX expressions must have one parent element.
Since I already have a condition for displaying data, is there a better way I can create this toggle component that would simplify how I access data?
Upvotes: 0
Views: 46
Reputation: 553
Check my approach. After I figured out the multiple elements issue, I met an IndexError as you were trying to access an unknown index in the toggle-able view.
Upvotes: 0
Reputation: 996
Multiple childs should be wrap into a parent dive and there is no any parent div in your map function. Check the code i have added comment. Try this:
import React, { useState } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import style from './style.css'
import data from './data.json'
const App = () => {
const [showConnections, setShowConnections] = useState(false);
const connex = data.tracks;
return (
<div className={style.interchange_connections}>
{/* default = closed */}
{!showConnections
? (
<div>
{connex.map((tracks) => (
<div
className={style.connection_container}
onClick={() => setShowConnections(!showConnections)}
onKeyPress={() => setShowConnections(!showConnections)}
role="button"
tabIndex="0"
>
<div span={1}>
</div>
<div span={3}>
<div className={style.vehicle_id}>
<p>{tracks.line_number}</p>
</div>
</div>
<div span={6}>
<span className={style.location_text}>
{tracks.origin}
</span>
<span> - </span>
<span className={style.location_text}>
{tracks.destination}
</span>
</div>
<div span={8}>
<div className={style.stop_point}>
<p>{tracks.stop_point}</p>
</div>
</div>
<div span={6}>
<span className={style.stop_point}>
<p>{tracks.arrival_time}</p>
</span>
</div>
</div>
))}
</div>
)
: (
<>
{/* opened view */}
<div>
{connex.map((tracks) => (
<div> {/* parent div */}
<div
className={style.connection_container}
onClick={() => setShowConnections(!showConnections)}
onKeyPress={() => setShowConnections(!showConnections)}
role="button"
tabIndex="0"
>
<div span={1}>
</div>
<div span={3}>
<div className={style.vehicle_id}>
<p>{tracks.line_number}</p>
</div>
</div>
<div span={6}>
<span className={style.location_text}>
{tracks.origin}
</span>
<span> - </span>
<span className={style.location_text}>
{tracks.destination}
</span>
</div>
<div span={8}>
<div className={style.stop_point}>
<p>{tracks.stop_point}</p>
</div>
</div>
<div span={6}>
<span className={style.stop_point}>
<p>{tracks.arrival_time}</p>
</span>
</div>
</div>
// start feed data
<div className={style.sub_container_wrapper}>
<div className={style.bracket} />
<div className={style.sub_container}>
<div span={1}>
</div>
<div span={2}>
<div className={style.vehicle_id}>
{tracks.feed[0].line_number} //use tracks not connex
</div>
</div>
</div>
</div>
</div> // parent div closed
))}
</div>
</>
)}
</div>
);
}
render(<App />, document.getElementById('root'));
Upvotes: 1
Reputation: 4195
You are using multiple element without react fragment or any element in index.js
line 63,
try something like this,
{connex.map((tracks) => (
<> {/*!! here !!*/}
<div
className={style.connection_container}
onClick={() => setShowConnections(!showConnections)}
onKeyPress={() => setShowConnections(!showConnections)}
role="button"
tabIndex="0"
>
<div span={1}>
</div>
<div span={3}>
<div className={style.vehicle_id}>
<p>{tracks.line_number}</p>
</div>
</div>
<div span={6}>
<span className={style.location_text}>
{tracks.origin}
</span>
<span> - </span>
<span className={style.location_text}>
{tracks.destination}
</span>
</div>
<div span={8}>
<div className={style.stop_point}>
<p>{tracks.stop_point}</p>
</div>
</div>
<div span={6}>
<span className={style.stop_point}>
<p>{tracks.arrival_time}</p>
</span>
</div>
</div>
// start feed data
<div>
<div className={style.sub_container_wrapper}>
<div className={style.bracket} />
<div className={style.sub_container}>
<div span={1}>
</div>
<div span={2}>
<div className={style.vehicle_id}>
{connex.feed[0].line_number}
</div>
</div>
</div>
</div>
</div>
</> {/*!! here !!*/}
))}
Upvotes: 1